[精讚] [會員登入]
428

【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

你可能感興趣的文章

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

【Wickct】(link) <a> 如何新增超連結 簡單來說有兩種方式,小編個人比較偏好 的方法

【MySQL】每個類別中取前三高 一個由多層次所組成的SELECT述句

【Discord bot】[botton]按鈕的使用、響應和關閉 Discord的botton通常都要和View配合使用。

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

【JAVA】[java.lang.Class]如何不透過new來實體化class 在某些極端狀態下,我們沒有辦法直接將實體化後的 Object 傳入函數內,只能採用傳入 Class 在實體化成物件這種極端的方式來進行

我有話要說

>>

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

訪客留言

[無留言]

隨機好文

【手遊介紹】小品手遊─寶箱是我的!(SUMMONER'S GREED) 輕鬆無腦的塔防遊戲,殺時間本小編推薦的遊戲之一

高捷少女:小穹與果仁巧克力㊦ 「如果妳跟一個女生同班三年,看過她午休流口水跟狼吞虎嚥地吃午餐,就算變成高捷代言人,也很難把她當女神的啦!」她說,小穹氣得搶走她義大利麵裡的蝦子,其他人笑得花枝招展。

高捷少女:購票大作戰② 一個不好的預感浮現,艾米莉亞開始檢查屋子四處。窗戶跟陽台都有關好,也沒有被打開的跡象。但一股無形的壓力,開始在寂靜的公寓中蔓延,她不安地嚥一下喉嚨。最後,她走向那扇窗戶,那前天晚上,白龍為了逃脫,而撞

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

高捷少女:美麗島的守護者⑤  雖然暫時不用怕牠們了,可是一直躲在這裡終究不是辦法,小雅心想。她看看四周,這間更衣室沒有窗戶或後門,她不禁著急起來,不可能一直躲在這裡面,但從門出去只會被群貓圍攻而已。小雅低下頭苦思該怎麼辦,過了不