[精讚] [會員登入]
477

【Wicket】[CSP] Content-Security-Policy & Content-Security-Policy-Report-Only

Wicket 預設開啟的,所以如果要加載外部資源甚至是同源資源都會被擋下。

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

分享連結 【Wicket】[CSP] Content-Security-Policy & Content-Security-Policy-Report-Only@小編過路君子
(文章歡迎轉載,務必尊重版權註明連結來源)
2022-05-20 16:41:58 最後編修
2022-03-24 14:33:41 By 過路君子
 

哈囉大家好,這裡是又踩進Wildfly大坑裡面的小編過路君子

Wicket 9.x API真的很過分,就放兩個函式在那裡,然後底下全白,誰知道在做什麼的。

 

 

那因為本篇文章高度相關 CSP,還不太了解的人可以參考由其他筆者所撰寫的這篇:Content Security Policy (CSP) — 幫你網站列白名單吧@Hannah Lin

或是直接生咬 W3C 所提供的完整原文文檔:Content Security Policy Level 3@W3C,這兩篇也是小編所參考的文獻資料。

小編這邊要特別提醒:不是使用了 CSP 就可以高枕無憂,CSP 只是我們眾多安全防線中的第一道而已,就算開啟,我們伺服器後端也要做校驗檔案之類的動作,相關的資訊可以參考這篇:前端防禦從入門到棄坑——CSP變遷@程序猿哪些事

 

那至於 Wicket 的 API 也有小小的提及,但是前提是建立在他們認為我們已經具有 CSP 的基本知識了,所以如果完全沒有 CSP 知識點進去會完全看不懂。

關於如何設定 CSP 和 Content-Security-Policy-Report-Only 可以參考這篇:org.apache.wicket.csp.ContentSecurityPolicySettings

關於 Wicket 有什麼 CSP 可以設定,可以參考這篇:org.apache.wicket.csp.CSPDirective

 

小編就是靠上面三篇文檔和硬咬 Wicket 9.x API 才終於搞懂的,不得不說,Wicket 這方面的資料網路上超級缺乏,沒什麼有用的資料可以參考。

其實小編有看到更為簡單粗暴的解法,這個小編下面會提到,簡單來說就是直接關閉 CSP,那樣是可以跑啦,但是一點都不優雅,小編不喜歡,就是喜歡搞自己。

所以才跑去讀了好幾遍 CSP 後好不容易搞懂,然後又要了解 Wicket 如何魔改 CSP,又要如何更訂 Wicket 原始預設值,最後才誕生出這篇筆記的。

 

這篇文章的主要目的是要記錄 Wicket CSP 該如何設定,那事實上 Wicket 有提供我們在這高強度的 CSP 下依舊可以使用外部 css 和 javascript 的(運用隨機 nonce)。

有興趣知道如何新增 css 或是 javascript 到我們當前頁面(直接使用 HTML 標籤,這兩者都會被 Wicket 預設的 CSP 擋下),可以參考這篇:【Wicket】[nonce]如何導入css以及javascript@小編過路君子

那在開始之前照慣例附上目錄結構:

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

 

 

當我們今天部屬好 Wicket 時,很高興地開始撰寫我們的網頁,那既然是網頁,想必 CSS 和 JavaScript 是不可少的吧!

所以我們就很高興的像平常一樣使用了 <link href="..." /> 或 <script scr="...">,結果竟然被 CSP 擋下來了......

然後仔細看了一下檔頭:

好傢伙,竟然 Wicket 預設連同源的 CSS 檔案也會拒絕掉。

不僅如此連 inline 和 <style type="text/css"></style> 也擋掉了,總之只要是 css 一律無效。

那各位可能會看到網路上其他人的解法是使用 <wicket:head></wicket:head> 來解決行內 css 或是 js,但對於外部檔案一樣無解。

 

那接下來我們就要開始對 CSP 動刀了,接下來的所有程式都是寫在 webRoute.java 內,index.html 以及 index.java 等等檔案都不需要做修正。

第一步當然就是要來取得我們整個網站的 CSP 設定了,Wicket 的 CSP 是以一個網站作為單位的,全站統一用一個 CSP。

那為了達成這個任務,我們首先要到我們的 WebApplication 下,以小編的例子來說是 webRoute.java 這個檔案,使用以下函式:

public class webRoute extends WebApplication
{
    @Override
    public void init()
    {
        getCspSettings();
    }
}

 

就這樣,但如果各位有偷偷看過 Wicket 9.x API 的話,應該不難發現我們後面還要接一個函式,根據 API 的解釋:

沒了。

真的是有夠搞笑,至少這樣寫一下吧!

blocking() reporting()
設定 Content-Security-Policy 設定 Content-Security-Policy-Report-Only

那 Wicket 預設不啟用 Content-Security-Policy-Report-Only,如果各位之後有自行啟用的話......記得要設定 report-to,要不然網頁會一直送出警告,就算沒有錯誤也一樣,很討厭。

 

其中 Wicket 對於這兩項的預設值如下,其中 nonce 後面接的數值每次頁面載入都會重新產生,所以這邊僅寫 nonce:

  Content-Security-Policy(CSP) Content-Security-Policy-Report-Only
default-src none -
script-src nonce
strict-dynamic
-
style-src nonce -
img-src self -
connect-src self -
font-src self -
anifest-src self -
child-src self -
frame-src self -
base-uri self -
report-to - -

表註:可能會有人發現,若真的有設定 report-to,實際去抓取檔頭的話會看到 Wicket 用的是 report-uri,那因為 report-uri 即將被淘汰,所以小編評估之後還是決定寫 report-to。

 

所以如果我們今天要設定 Content-Security-Policy 要這樣寫:

public class webRoute extends WebApplication
{
    @Override
    public void init()
    {
        getCspSettings().blocking();
    }
}

反之,如果只是要設定 Content-Security-Policy-Report-Only 要這樣寫:

public class webRoute extends WebApplication
{
    @Override
    public void init()
    {
        getCspSettings().reporting();
    }
}

那如果兩個都要設定就都寫,簡單吧!

 

接下來就是重頭戲了,我們要開始添加、移除或是關閉 CSP 規則了。

那 Wicket 官方也很好心的提供了四個快速建構式給我們,分別是:

  strict() disabled() clear() unsafeInline()
default-src none - - none
script-src nonce
strict-dynamic
- - self
unsafe-eval
unsafe-inline
style-src nonce - - self
unsafe-inline
img-src self - - self
connect-src self - - self
font-src self - - self
anifest-src self - - self
child-src self - - self
frame-src self - - self
base-uri self - - self
report-to - - - -

其中的 strict() 設定有沒有眼熟呢?對,我們的 Wicket 預設值就是 strict()。

 

這也是為什麼現在看到網路上的解法有些人就叫你直接下:

public class webRoute extends WebApplication 
{
    @Override
    public void init()
    {
        getCspSettings().blocking().disabled();
    }
}

然後我們照著下,唉!可以跑了,我的資源正常載入了!

看了上表之後我們就可以理解了,因為我們直接把 CSP 關掉了嘛!俗話說的好,解決不了問題就解決提出問題的人。

所以其實下 getCspSettings().blocking().clear(); 也有同樣的效果。

 

那關於設定 SCP 的方式有以下四種:

add() remove() reportBackAt() setAddLegacyHeaders()
添加 SCP 指定項狀態 完全移除 SCP 指定項設定 設定 report-to 的網址路徑 是否啟用 Legacy 來相容其他瀏覽器,像是 IE

 

那可以設定的 SCP 總共有以下 16 種。

這邊要注意的是:要先 import org.apache.wicket.csp.CSPDirective; 才能使用喔。

Wicket CSP 屬性 對應的 CSP 值
BASE_URI base-uri
CHILD_SRC child-src
CONNECT_SRC connect-src
DEFAULT_SRC default-src
FONT_SRC font-src
FRAME_ANCESTORS frame-ancestors
FRAME_SRC frame-src
IMG_SRC img-src
MANIFEST_SRC manifest-src
MEDIA_SRC media-src
OBJECT_SRC object-src
REPORT_URI report-uri
SANDBOX sandbox
SCRIPT_SRC script-src
STYLE_SRC style-src
WORKER_SRC worker-src

 

那對每個設定可以添加的值有以下七種。

這邊也要注意的是:要先 import org.apache.wicket.csp.CSPDirectiveSrcValue; 才能使用喔。

Wicket CSP 值 對應的 CSP 值
NONCE nonce-xxx
NONE none
SELF self
STRICT_DYNAMIC strict-dynamic
UNSAFE_EVAL unsafe-eval
UNSAFE_INLINE unsafe-inline
WILDCARD *

表註:nonce後面所接的值 Wicket 會自動幫我們產生,我要只要填入 NONCE 即可。

 

那我們一個一個來看,先從最簡單的 setAddLegacyHeaders() 來看好了,我們先看看關於此函式的介紹:

由上圖我們可以知道,此函數接受一個 boolean 值,而且預設為關閉。

所以如果我們今天要打開此項設定,應該要這樣下:

@Override
public void init()
{
    getCspSettings().blocking()
        .setAddLegacyHeaders(true);
}

當我們重新載入頁面之後就可以看到我們的檔頭裡多了 X-Content-Security-Policy 的屬性。

而且相關的設定跟我們目前的 Content-Security-Policy 一模一樣喔。

 

第二個小編緊接著要來介紹的是 reportBackAt(),一樣先來看看有關此函式的說明:

由上圖的函式說明我們可以得知,此函數接受一個字串,而這個字串就是要瀏覽器將使用者違反相關的 CSP 資訊傳送到我們所指定的地方。

所以如果小編想要瀏覽器將相關資訊傳送到 http://192.168.88.128:8080/CSPwarning,那我們應該要這樣下指令:

public class webRoute extends WebApplication
{
    @Override
    public void init()
    {
        getCspSettings().blocking()
            .reportBackAt("http://192.168.88.128:8080/CSPwarning");
    }
}

然後我們再次重新載入網頁。

瞧~現在我們的檔頭的 Content-Security-Policy 這欄是不是出現了剛剛一直都沒有看到的 report-uri 呢?

那各位啟用前要對於處理這些訊息做一些規範,包括短時間內大量的 CSP 警告接收,如果對方真的有心,那這也是一種 DDoS 攻擊。

 

那接下來要來介紹的就是 remove() 囉,照慣例我們先來一起看 API 對於此函式給出的說明吧~

根據上圖我們可以得知,只要將我們想要移除項目填入,就可以成功將其移除掉囉。

import org.apache.wicket.csp.CSPDirective;

public class webRoute extends WebApplication
{
    @Override
    public void init()
    {
        getCspSettings().blocking()
            .remove(CSPDirective.STYLE_SRC)      //移除 style-src
            .remove(CSPDirective.SCRIPT_SRC);    //移除 script-src
    }
}

這邊小編示範移除原預設 CSP 裡的 style-src 和 script-src 屬性,若要移除其他屬性可以參照上表,換成要移除的屬性即可。

那根據 Wicket 9.x API 上所寫的,小編沒有找到只移除某一屬性某個值的函式,所以目前要刪除屬性的某一值的話......只能全部移除再添加回來其他不須刪除的。

 

最後一個函數!沒錯,終於來到了最後一個函式 add() 了。

就像剛剛一樣,來吧。

那不同於 remove() 是移除整個屬性,每次 add() 都只會增加某一屬性的指定值。

import org.apache.wicket.csp.CSPDirective;
import org.apache.wicket.csp.CSPDirectiveSrcValue;

public class webRoute extends WebApplication
{
    @Override
    public void init()
    {
        getCspSettings().blocking()
                /* 在 font-src 裡添加 nonce-xxx */
            .add(CSPDirective.FONT_SRC, CSPDirectiveSrcValue.NONCE)

                /* 在 style-uri 裡添加 self */
            .add(CSPDirective.REPORT_URI, CSPDirectiveSrcValue.SELF);
    }
}

所以我們在使用的時候就要告訴 Wicket 我們要設定什麼屬性的什麼值對不對~

 

 

那這就是 Wicket 的 CSP 全操作了,其中小編有省略掉解釋 CSP 屬性所代表的意義,像是 STYLE_SRC 是用來限定可執行 Css 來源或是 SCRIPT_SRC 是用來限定可執行 JavaScript 來源等等。

那其實 Wicket 已經有內建導入外部 Script 或是 Css 的方法了,各位想到了嗎?那小編這邊也不賣關子了,簡單來說就是使用 nonce 啦!

相關的資訊可以參考小編的這篇文章:【Wicket】[nonce]如何導入css以及javascript@小編過路君子

 

 

 

後記

其實當下小編一得知是因為 CSP 才會造成資源無法加載,就跑去找其他人是怎麼解決這個問題,發現絕大部份就是教你直接關閉 CSP,然後原發問者就很高興的在下面回覆:「它有用,開始運作了!」小編看到真的是額頭三條線冒出來......相當的不以為意,小編就不信邪小編不能在不更動 Wicket 預設 CSP 的狀況下使用小編想要的資源。

然後花了兩天去研讀 CSP,然後又花了一天去了解要怎麼使用 Wicket 來全面控制 CSP,最後又花了一天來寫這篇文;那你問小編最後有沒有解決問題,當然有!就是使用 nonce,而且除了同源之外還可以加載外部的資源檔案喔!

下圖的 nonce 是 Wicket 自己產生的,所以每次載入頁面所顯示的值都不一樣,詳細的步驟小編寫在了此文章末的那篇文章了。

END

你可能感興趣的文章

【Maven】如何夾帶檔案至Jar內以及其讀取方式 想要讀取一個外部的文字文件?Maven是你的好幫手

【Docker&Wildfly】(bitnami/wildfly)如何從零開始創建網頁伺服器 使用他人的 docker image 來架設我們的 wildfly web server

【Python3】11 - 字典(Dictionary)的使用範例 python3的幾個字典使用範例,改寫自他人perl的範例

【MEGAcmd】[Linux] 如何解決Unable to connect to service: error=2 用了好久的軟體突然停止一切的運作了。

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

【Maven / Jython】建立可直接執行的JAR檔案 以小編的前一篇文章為基礎,加了一些新東西進去,就變成另一個樣貌了

我有話要說

>>

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

訪客留言

[無留言]

隨機好文

[活動] 2017年4/1雲空幻想愚人節活動彩蛋&攻略 (紀念性質) 雲空幻想2017年的愚人節活動介紹同時也是本小編的第一篇網路文章(*^ω^)♪

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

高捷少女:地下城的探險少女① 婕兒心中一奇,便走上前看著仔細。那塊凹進去的地方中心大約三公分厚,越往邊緣就越淺,圓型直徑十五公分。婕兒拿出銅盤對比一下,發現兩者大小竟然一致,銅盤似乎能夠完整的嵌進去。     婕兒看著凹槽,心中

高捷少女:美麗島的守護者(終) 「我是她的師娘,妳一定就是艾米莉亞吧?小雅昨晚有跟我說到您。」「師娘?」艾米疑惑不解。

艾米莉亞和高捷戀旅3① 「既然艾米莉亞小姐也來了,就把那個拿出來吧。」美麗島捷運商店的負責人說完,一名工作人員推著一個大箱子進入辦公室。他將箱子打開,將裡面的東西抬出來。艾米張大嘴巴