[精讚] [會員登入]
334

【Wicket】[nonce]如何導入css以及javascript

如果只是用一般的 HTML link 或是 script 標籤來寫,會被 CSP 擋住,禁止加載資源,那我們除了關閉 CSP 以外還有沒有辦法來解決呢?

分享此文連結 //n.sfs.tw/15705

分享連結 【Wicket】[nonce]如何導入css以及javascript@小編過路君子
(文章歡迎轉載,務必尊重版權註明連結來源)
2022-05-20 16:41:16 最後編修
2022-03-25 08:24:42 By 過路君子
 

哈囉大家好,這裡是找到好方法的小編過路君子

看大家都只說用 CssHeaderItem.forReference() 但是小編一直在想......所以那些人的 CSS 檔案到底放在哪裡?

 

 

如果各位有到 Stackoverflow 之類的網站先去找資料的話,應該不難發現很多人都叫我們這樣寫:

import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.request.resource.CssResourceReference;

@Override
public void renderHead(IHeaderResponse response)
{
    response.render(CssHeaderItem.forReference(new CssResourceReference(myCssFile.class, "myCssFile.css")));
}

那現在問題來了,這幾行要寫在哪裡?css 檔案要放在哪裡?需要掛載 css 檔案嗎?

 

先說結論,小編在一陣摸索之後看了以下的訊息:

(所有圖片點擊都可以放大、變高清)

那小編看了以下的輸出至少得知了好像要把 css 打包成 package,但是真的有夠麻煩的

 

所以我們今天不會使用這個方式。

我們直接使用網址的方式,換言之,就是只要寫網址進去就可以了,不用管這個 css 或是 javascript 是同源還是外部的,只要有網址就可以了。

如果真的有需要使用第三方的資源檔,那還是使用小編等等介紹的方式,就算該程式碼帶有惡意,我們最少還是有機會擋下來的。

有關 XSS 的更多資訊可以參考這篇他人的文章:前端防禦從入門到棄坑——CSP變遷@程序猿哪些事

那如果今天我們真的需要從其他網站獲取資訊(例如:溫度、濕度)怎麼辦?也很簡單,就是去設定一下 CSP 的 connect-src 即可,如何設定可以參考這小編這篇文章:【Wicket】[CSP] Content-Security-Policy & Content-Security-Policy-Report-Only@小編過路君子

 

那我們在開始前,照慣例小編一樣先附上目錄結構:

小編會將 css 和 js 放在 webapp 下,而不是 java 下的原因是:

放在 webapp 下走的是 web.xml 的設定,網址就是路徑;但若放在 java 下走的就是 webRoute.java 的設定,網址預設又臭又長,若要漂亮的網址就要掛載,那既然掛載了,不就跟我們直接放在 webapp 一樣?

 

 

如何加載 CSS

因為 CSS 相對起來比較單純,所以我們從這邊開始。

那以我們今天要在 index.html 新增 index.css 為例,假設今天 index.css 內有以下內容:

接著,我們打開 index.java 添加以下的程式碼:

import org.apache.wicket.request.Url;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.CssReferenceHeaderItem;

public class index extends WebPage
{
    @Override
    public void renderHead(IHeaderResponse response)
    {
        /* 取得目前網頁網址 */
        Url url = RequestCycle.get().getRequest().getUrl();
        String fullUrl = RequestCycle.get().getUrlRenderer().renderFullUrl(url);

        String rootUrl;
        try {rootUrl = fullUrl.substring(0, fullUrl.indexOf('/', fullUrl.indexOf('/')+2));}
        catch(Exception error) {rootUrl = fullUrl;}

        /* 渲染CSS */
        response.render(CssReferenceHeaderItem.forUrl(rootUrl + "/css/index.css"));
    }
}

那其中因為小編都是使用 Wildfly 所以之前網址可能只會打 /css/index.css 這樣,但沒想到在 Apache 上面踢到大鐵板,Apache 的相對連結算法跟 Wildfly 不一樣啊!

所以現在小編不管如何都一定使用網址進行連結,這樣就沒有這個問題了;如果有興趣了解更多可以參考這篇文章:【Wicket】[URI]使用Java取得目前網址@小編過路君子

那這邊有一點要注意的是,我們不用在 HTML 裡面添加 <link href="..." />,Wicket 會自動幫我們產生,所以我們的 HTML 維持原本的樣子即可。

接著刷新頁面。

我們的 CSS 漂亮的出現了!而且還帶有 nonce,所以不會被 CSP 攔下。

 

那如果我們今天要加載的是來自其他網站的 css 呢?那剛好,小編到精讚上隨便抓了一個 css 檔來測試(原檔在這:flags.css)。

一樣的程式碼,如法炮製。

import org.apache.wicket.request.Url;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.CssReferenceHeaderItem;

public class index extends WebPage
{
    @Override
    public void renderHead(IHeaderResponse response)
    {
        /* 取得目前網頁網址 */
        Url url = RequestCycle.get().getRequest().getUrl();
        String fullUrl = RequestCycle.get().getUrlRenderer().renderFullUrl(url);

        String rootUrl;
        try {rootUrl = fullUrl.substring(0, fullUrl.indexOf('/', fullUrl.indexOf('/')+2));}
        catch(Exception error) {rootUrl = fullUrl;}

        /* 渲染第三方CSS */
        response.render(CssReferenceHeaderItem.forUrl("https://n.sfs.tw/web/css/flags.css"));
    }
}

重新載入網頁並套用對方 css 的屬性。

不要問小編為什麼控制台和網頁原始碼的 HTML 不一樣,因為小編截圖之後才想到要設一個屬性來測試,所以就臨時用 javascript 添加上去。

總之,我們的資源成功載入,屬性也成功套用,完全沒受到半點 CSP 的攔截。

對了,如果對方的 css 內有網址,例如 background: url("..."),那網址的部分照樣會被攔截,所以最好的辦法就是將所有相依資源移到我們本機,因為預設圖片等等是同源 ok 的。

 

 

如何加載 Javascript

如果只是要添加沒有對外互動的 javascript 的話相當單純,絕對不會被 CSP 攔截。

可是一旦發出網頁請求,就會看對方是什麼類型的資源,然後比對該項 CSP,如果是不被允許的,那照樣會直接禁止傳輸。

那我們一樣要在 index.html 裡面加載 index.js 檔案,假設 index.js 內有以下的程式碼:

打開 index.java 添加以下程式碼:

import org.apache.wicket.request.Url;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;

public class index extends WebPage
{
    @Override
    public void renderHead(IHeaderResponse response)
    {
        /* 取得目前網頁網址 */
        Url url = RequestCycle.get().getRequest().getUrl();
        String fullUrl = RequestCycle.get().getUrlRenderer().renderFullUrl(url);
        String rootUrl = fullUrl.substring(0, fullUrl.indexOf('/', fullUrl.indexOf('/')+2));

        /* 渲染javascript */
        response.render(JavaScriptReferenceHeaderItem.forUrl(rootUrl + "/css/index.js"));
    }
}

接著同樣刷新網頁頁面。

跟上面的 CSS 一樣,我們使用網址漂亮的渲染出了 javascript,一樣如果對 Wicket 使用 java 擷取網址有興趣的人這邊請:【Wicket】[URI]使用Java取得目前網址@小編過路君子

小編沒在精讚上面找到比較適合拿來做示範的第三方 javascript,所以示範的部分跳過,但大體邏輯跟 css 一樣:

/* 渲染第三方 javascript */
response.render(JavaScriptReferenceHeaderItem.forUrl("http://uri.here"));

那跟 css 一樣,javascript 如果會像其他的網站發出資源請求,會看請求的資源類型,然後對照相對應的 CSP,若是不符合規則則同樣會禁止存取。

所以如果需要請求其他資源的話,要嘛下載回來放本機,要嘛去修改 CSP 規則,同意下載。

如果是 css 和 javascript 那就算是同源照樣禁止傳輸,最好的辦法是像上面那樣在一開始就渲染好並放到 head 裡,這樣連請求都不用,直接呼叫函式即可。

 

 

 

後記

這樣看起來好像不難對不對,小編也是這麼想。

但是不知道網路上為什麼就是沒有人給出這樣的解法,都只能看到使用 forReference() 的方法,最後小編是跑去 Wicket 9.x API 裡面瞎找,結果還真的讓小編找到了(org.apache.wicket.markup.head.CssHeaderItem)。

沒錯,forUrl() 跟 forReference() 是同一個 class 下的函式,但是卻沒有人提及,想想也是搞笑,因為官方的文檔裡面也是使用 forReference()

END

你可能感興趣的文章

【Linux】[CentOS 8]如何更新sudo指令 上次會想要更新sudo這個指令的時間應該是2017年了吧?轉眼間就2021了耶

【Wickct】如何製作一個簡單的動態響應頁面和傳遞參數至其他頁面 身為一個後端架構程式,這個功能當然是非常重要之一

【C++】class練習 — 檢測該字串是否為迴圈 第一次的C++結構式寫法,雖然以後應該會見怪不怪,但畢竟是第一次所以還是想保存下來

【Docker hub】[Linux]以IPv6來pull容器(container)吧! 在一個 IPv6 還不盛行的年代,做事情總是特別麻煩

【Vim】解決貼上文字時出現過多空格的問題 換了新系統,有時候就算重裝軟體並且複製了設定檔也還是會出現非常奇怪的現象

【Maven】[Wicket](Java) 如何部署Wicket到Wildfly內 Wicket 是一個 Java 下的套件,換言之,我們的網頁伺服器後端是由 Java 來撰寫的

我有話要說

>>

限制:留言最高字數1000字。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

高捷少女:小穹與果仁巧克力㊤ 阿敏突然輕笑一聲,從櫃臺拿來一個塑膠餐盒,打開給大家看。「這是小穹烤的餅乾,妳們吃吃看就知道她為什麼不想講了。」小穹變得緊張起來。「阿敏,妳怎麼還留著呀?」艾米莉亞、婕兒與耐耐各自拿了一塊,把夾著奶油

高捷少女:地下城的探險少女③ 過了十分鐘後,前方的天花板滴下一滴水珠,發出「噠」一聲響亮地落在石地上,讓大家嚇一跳。     「什麼嘛,只是水珠而已。」艾米撫著胸口噓了一聲。     忽然間,耐耐的臉色發白起來。「各位,你們看

高捷少女:地下城的探險少女④ 耐耐突然抖了一下。「妳們聽到了嗎?」她說。「聽到什麼?」婕兒問。「那個腳步聲啊!」耐耐嚥了一下喉嚨,覺得有些害怕。「有一陣腳步聲經過,很小聲,但我還是聽到了。』「妳聽錯了吧……等等!」婕兒使終維持著將

高捷少女:美麗島的守護者① 婕兒跟耐耐嚇得臉色發白。「耐耐,小穹有這方面的愛好喔?」婕兒小聲地說。耐耐默默的拿出筆記本,臉上浮現一層微笑:「這麼大的新聞,要趕快記下來!」

高捷少女:美麗島的守護者③ 小雅閉上眼睛,思索在高捷發生的點點滴滴。她心意已決,在高捷的日子的確也有快樂的部分,不過她相信換個方向是更好的決定。有關高捷的所有美好回憶,小雅決定保留在心裡就好,繼續在高捷工作只會讓自己更痛苦而已,