[精讚] [會員登入]
46

【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

你可能感興趣的文章

【C++】使用SFML創建新視窗和新增圖標(ICON)並隱藏DOS 筆記,怕自己以後忘記怎麼創建並開啓一個新視窗

【Maven】如何開始撰寫 Minecraft PaperMC server插件 萬事起頭難,要開始寫一個插件最難的一步就是要怎麼開始寫

【Maven】如何創建一個簡單可部屬的WAR檔 滿重要的一個大功能,在使用JAVA網頁伺服器的時候一定會需要這個WAR檔來進行部屬

【Maven】用Maven來託管Wildfly/jBoss的部屬(deploy)、解部屬(undeploy) 極簡版,給未來想要抄作業的小編自己,完整的一切設定檔,可以依照個人需求作增刪。

【C++】使用SFML製作讓方塊落下的畫面 從開啟新視窗延伸過來的應用(?),配合上一篇所使用到開啟一個可渲染視窗的那堆程式碼的延伸。

【Maven】如何創建一個簡單可執行的JAR檔 滿重要的一個小功能,畢竟有時候是要傳遞的是JAR檔,而不是直接透過Maven直接部屬之類的

我有話要說


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

訪客留言

[無留言]

隨機好文

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

高捷少女:耐耐的新年驚喜① 耐耐拿出手機。「我回來囉。」她說。幾分鐘後,木門緩緩打開。當它完全開啟的那一刻,小穹手中的包包掉到地上;艾米揉揉雙眼,確定自己看見的景象;婕兒的三魂七魄飛到了九霄雲外。

【歌評】蓮台野夜行 -古の冥界寺 古老的冥界寺 冥界?那是什麼地方?該不會是像地獄那樣的地方吧?!

【想法】關於網路上的謾罵這檔事 網路是個自由的世界,每個人都享有平等的發言權,但是,請永遠記得,在網路上漫罵別人一定會留下證據的,就算之後刪文,你怎能確保對方沒有截圖存證?

【感想】蓮台野夜行 - 東方妖妖夢 東方妖々夢 ~Ancient Temple 再撰 一首歌聽一遍跟聽100遍是一樣的,但是,今天聽跟明天再聽感覺絕對會不一樣。