[精讚] [會員登入]
548

【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

你可能感興趣的文章

【JDA/discord bot】如何獲得訊息中的圖片和影片並儲存或轉傳 如何將訊息中的圖片或影片之類的多媒體提取出來之後,再進行相關的處理

【Firefox \ Maven】[Headless](Linux) 如何使用Maven打包並驅動Firefox 有時候我們需要取得渲染後的網頁,當然是直接呼叫瀏覽器出來用啦

【C++】使用struct array和一維int array模擬二維int array 主要是因為用sort去排序int array的二維陣列小編懶得研究,於是就研究了一種維持一維陣列但是有二維陣列效果的程式,小編就廢~~

【PaperMC - API】如何發送指令到伺服器內 How to sending or executing commands to server

【JDA/discord bot】package does not exist fix JDA 4.0 和 5.0 差別還是很大的

【Wicket】[Header]如何讀取來自客戶端地檔頭和傳送自訂擋頭至客戶端 當需要設定檔頭或是讀取來自客戶端的檔頭時,這些程式碼就很好用

我有話要說

>>

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

訪客留言

[無留言]

隨機好文

希萌創意預計在今年7月繼東津萌米之後再次推出新遊戲--食用性少女! 今天來介紹希萌創意的心企劃案,來讓大家知道這個消息!讓大家的錢包君一起來減肥吧!Ψ(☆w☆)

高捷少女:地下城的探險少女⑤ 小穹寫好後,耐耐看了一遍。「我想我應該辦得到。」她說完跪坐在地上,然後把古箏安放在大腿上,並將樂譜放在前面的地板。「要開始囉。」耐耐閉上眼睛,深呼吸一口氣,小穹等人在一旁看著她,心中暗自替她打氣。

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

高捷少女:耐耐的新年驚喜④ 「雖然夫人一直有在保養身體,可是年紀畢竟不小了,醫生曾經說過,不管是不是假性陣痛,一旦夫人有感覺了便立刻送到醫院。」管家爺爺說:「我們已經打電話給附近的大型醫院,救護車很快便會來到這裡。」「去看伯母吧

【歌評】蓮台野夜行 - 幻想的永遠祭 蓮台野的探險雖然結束了,但是,誰知道是不是一段新的探險的序曲呢?