spring Security 4增加了對保護spring的網絡套接字支持的支持。本節描述如何使用Spring Security的網絡套接字支持。
您可以在samples/javaconfig/chat中找到一個完整的WebSocket安全性工作示例。
直接JSR-356支持
Spring Security不提供直接的JSR-356支持,因為這樣做沒有什么價值。這是因為格式未知,所以Spring無法保護未知格式。此外,JSR-356沒有提供攔截消息的方法,因此安全性將是相當有侵害性的。
23.1 WebSocket Configuration(網絡套接字配置)
Spring Security4.0通過Spring 消息傳遞抽象引入了對網絡套接字的授權支持。要使用Java配置配置授權,只需擴展抽象安全性套接字消息攔截配置器並配置消息安全性數據源注冊表。例如:

這將確保:
1、 任何入站連接消息都需要有效的CSRF令牌來實施相同的源策略。
2、對於任何入站請求,SecurityContextHolder都是在簡單用戶頭屬性中填充用戶的。
3、我們的信息需要適當的授權。具體來說,任何以“/user/”開頭的入站消息都需要ROLE_USER。關於授權的更多細節可以在第23.3節“網絡套接字授權”中找到。
Spring Security還為保護網絡套接字提供了XML命名空間支持。類似的基於XML的配置如下所示:

這將確保:
1、 任何入站連接消息都需要有效的CSRF令牌來實施相同的源策略。
2、對於任何入站請求,SecurityContextHolder都是在簡單用戶頭屬性中填充用戶的。
3、我們的信息需要適當的授權。具體來說,任何以“/user/”開頭的入站消息都需要ROLE_USER。關於授權的更多細節可以在第23.3節“網絡套接字授權”中找到。
23.2 WebSocket Authentication(網絡套接字認證)
網絡套接字重用與建立網絡套接字連接時在超文本傳輸協議請求中發現的相同的身份驗證信息。這意味着HttpServletRequest上的主體將被移交給網絡套接字。如果您使用的是Spring Security,則HttpServletRequest上的主體將被自動覆蓋。
更具體地說,為了確保用戶已經對您的網絡套接字應用程序進行了身份驗證,所有需要做的就是確保您設置了Spring Security來對您的基於HTTP的網絡應用程序進行身份驗證。
23.3 WebSocket Authorization(網絡套接字授權)
Spring Security 4.0通過Spring消息傳遞抽象引入了對網絡套接字的授權支持。要使用Java配置來配置授權,只需擴展抽象安全性套接字消息攔截配置器(AbstractSecurityWebSocketMessageBrokerConfigurer )並配置消息安全性數據源注冊表(MessageSecurityMetadataSourceRegistry)。例如:

這將確保:
1、任何沒有目的地的消息(即除消息類型或訂閱之外的任何消息)都需要用戶進行身份驗證。
2、任何人都可以訂閱/用戶/隊列/錯誤。
3、任何以“/app/”開頭的消息都要求用戶具有角色“ROLE_USER”。
4、任何以“/user/”或“/topic/friends/”開頭的訂閱類型的消息都需要ROLE_USER。
5、message或SUBSCRIBE類型的任何其他消息都會被拒絕。由於6,我們不需要這一步,但它說明了如何匹配特定的消息類型。
6、任何其他消息都會被拒絕。這是一個好主意,以確保您不會錯過任何消息。
Spring Security還為保護網絡套接字提供了XML命名空間支持。類似的基於XML的配置如下所示:

這將確保:
1、任何沒有目的地的消息(即除消息類型或訂閱之外的任何消息)都需要用戶進行身份驗證。
2、任何人都可以訂閱/用戶/隊列/錯誤。
3、任何以“/app/”開頭的消息都要求用戶具有角色“ROLE_USER”。
4、任何以“/user/”或“/topic/friends/”開頭的訂閱類型的消息都需要ROLE_USER。
5、message或SUBSCRIBE類型的任何其他消息都會被拒絕。由於6,我們不需要這一步,但它說明了如何匹配特定的消息類型。
6、任何其他消息都會被拒絕。這是一個好主意,以確保您不會錯過任何消息。
23.3.1 WebSocket Authorization Notes(網絡套接字授權說明)
為了正確保護您的應用程序,理解Spring的WebSocket支持非常重要。
WebSocket Authorization on Message Types(消息類型的網絡套接字授權)
理解SUBSCRIBE和MESSAGE消息類型之間的區別以及它在Spring中的工作方式非常重要。
考慮一個聊天應用程序。
1、系統可以通過“/主題/系統/通知”的目的地向所有用戶發送通知消息
2、客戶可以通過訂閱“/主題/系統/通知”來接收通知。
雖然我們希望客戶端能夠訂閱“/topic/system/notifications”,但我們不希望讓它們能夠向該目的地發送消息。如果我們允許向“/topic/system/notifications”發送消息,那么客戶端可以直接向該端點發送消息並模擬系統。
通常,應用程序會拒絕向以代理前綴(即“/topic/”或“/queue/”)開頭的消息發送任何消息。
WebSocket Authorization on Destinations(目標上的網絡套接字授權)
了解目的地是如何轉變的也很重要。
考慮一個聊天應用程序。
1、用戶可以通過向“/app/chat”的目的地發送消息來向特定用戶發送消息。
2、應用程序看到消息,確保“發件人”屬性被指定為當前用戶(我們不能信任客戶端)。
3、然后,應用程序使用將消息發送給接收者SimpMessageSendingOperations.convertAndSendToUser("toUser", "/queue/messages", message).
4、消息被轉到“"/queue/user/messages-<sessionid>”的目的地。
使用上面的應用程序,我們希望允許我們的客戶端監聽“/user/queue”,它被轉換為“/queue/user/messages-< session id >”。但是,我們不希望客戶端能夠監聽“/queue/*”,因為這將允許客戶端看到每個用戶的消息。
一般來說,應用程序通常會拒絕向以代理前綴(即“/topic/”或“/queue/”)開頭的消息發送任何SUBSCRIBE。當然,我們可能會提供一些例外來解釋類似的事情
23.3.2 Outbound Messages(出站消息)
Spring包含一個名為消息流的部分,描述了消息如何在系統中流動。需要注意的是,Spring Security只能保護客戶端的安全。Spring Security不會嘗試保護客戶端邊界通道。
最重要的原因是性能。對於每一條進入的消息,通常會有更多的消息出去。我們鼓勵保護對端點的訂閱,而不是保護出站消息。
23.4 Enforcing Same Origin Policy(執行相同來源政策)
需要強調的是,瀏覽器不會對網絡套接字連接強制執行相同的源策略。這是一個極其重要的考慮因素。
23.4.1 Why Same Origin?(為什么來源相同?)
考慮以下場景。一名用戶訪問bank.com,並對其帳戶進行身份驗證。同一個用戶在瀏覽器中打開另一個標簽,訪問evil.com。相同來源政策確保evil.com不能向bank.com讀寫數據。
對於網絡套接字,同一來源策略不適用。事實上,除非bank.com明確禁止,否則evil.com可以代表用戶讀寫數據。這意味着用戶可以通過網絡套接字做的任何事情(即轉賬),evil.com可以代表該用戶做。
由於SockJS試圖模仿網絡套接字,它也繞過了相同來源策略。這意味着開發人員在使用SockJS時需要明確地保護他們的應用程序不受外部域的影響。
23.4.2 Spring WebSocket Allowed Origin(Spring網絡套接字允許的來源)
幸運的是,由於Spring 4.1.5,Spring的網絡套接字和SockJS支持限制了對當前域的訪問。spring安全增加了一層額外的保護,提供縱深防御。
23.4.3 Adding CSRF to Stomp Headers
默認情況下,任何連接消息類型都需要CSRF令牌。這確保了只有能夠訪問CSRF令牌的站點才能連接。因為只有同一個源可以訪問CSRF令牌,所以不允許外部域建立連接。
通常,我們需要在一個超文本傳輸協議頭或一個超文本傳輸協議參數中包含CSRF令牌。然而,SockJS 不允許這些選擇。相反,我們必須在踏腳標題中包含令牌.
應用程序可以通過訪問name_csrf的請求屬性來獲取CSRF令牌。例如,下面將允許訪問JSP中的CsrfToken:

如果您使用的是靜態的超文本標記語言,那么您可以在一個REST 端點上公開這個CsrfToken。例如,下面將在URL /csrf上公開CsrfToken

JavaScript可以對端點進行REST調用,並使用響應來填充頭名和令牌。
我們現在可以將令牌包含在踏腳客戶端中。例如:

23.4.4 Disable CSRF within WebSockets(在網絡套接字中禁用CSRF)
如果您想允許其他域訪問您的站點,您可以禁用Spring Security的保護。例如,在Java配置中,您可以使用以下內容:

23.5 Working with SockJS
SockJS提供后備傳輸來支持舊的瀏覽器。當使用回退選項時,我們需要放松一些安全約束,以允許SockJS使用Spring Security。
23.5.1 SockJS & frame-options
SockJS可以使用利用iframe的傳輸。默認情況下,Spring Security會拒絕網站被陷害,以防止點擊劫持攻擊。為了使基於框架的傳輸能夠工作,我們需要配置Spring Security來允許相同的源來框架內容。
您可以使用框架選項元素來自定義框架選項。例如,下面將指示Spring Security使用“X-Frame-Options: SAMEORIGIN”,它允許在同一個域中使用iframe:

同樣,您可以使用以下內容自定義框架選項,以便在Java配置中使用相同的原點:

23.5.2 SockJS & Relaxing CSRF
SockJS對任何基於超文本傳輸協議的傳輸的連接消息使用開機自檢。通常,我們需要在一個超文本傳輸協議頭或一個超文本傳輸協議參數中包含CSRF令牌。然而,社會團體不允許這些選擇。相反,我們必須按照第23.4.3節“將CSRF添加到踏腳標頭”所述,將令牌包含在踏腳標頭中。
這也意味着我們需要放松對網絡層的CSRF保護。具體來說,我們想為我們的連接網址禁用CSRF保護。我們不想為每個網址禁用CSRF保護。否則我們的網站將容易受到CSRF的攻擊。
我們可以通過提供一個CSRF請求匹配器輕松實現這一點。我們的Java配置使這變得非常簡單。例如,如果我們的踏腳端點是“/chat”,我們可以使用以下配置僅對以“/chat/”開頭的網址禁用CSRF保護:

如果我們使用基於XML的配置,我們可以使用csrf@request-matcher-ref。例如:
