SpringBoot +spring security 與CSRF有關的幾個 問題

1、問題

​ 開啓 csrf 後 列表頁面沒有數據

​ 頁面console.log(403)

HTTP Status 403-Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

2、科普

​ 首先,科普一下,什麼是"CSRF"?

​ 這是一個web應用安全的問題,CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲“One Click Attack” 或者Session Riding,***方通過僞造用戶請求訪問受信任站點。

客戶端與服務端在基於http協議在交互的數據的時候,由於http協議本身是無狀態協議,後來引進了cookie的 方式進行記錄服務端和客戶端的之間交互的狀態和標記。cookie裏面一般會放置服務端生成的session id(會話ID)用來識別客戶端訪問服務端過 程中的客戶端的身份標記。

​ 再科普一下,什麼事"跨域" ?

​ 同一個ip、同一個網絡協議、同一個端口,三者都滿足就是同一個域,否則就有跨域問題 ,在跨域 的情況下 session id可能會被惡意第三方劫持,此時劫持這個session id的第三方會根據這個session id向服務器發起請求,此時服務器收到這個請求會 認爲這是合法的請求,並返回根據請求完成相應的服務端更新。

3、spring security 中的幾個關鍵點

​ 1)如果這個http請求是通過get方式發起的請求,意味着它只是訪問服務器 的資源,僅僅只是查詢,沒有更新服務器的資源,所以對於這類請求,spring security的防禦策略是允許的;

​ 2)如果這個http請求是通過post請求發起的, 那麼spring security是默認攔截這類請求的,因爲這類請求是帶有更新服務器資源的危險操作,如果惡意第三方可以通過劫持session id來更新 服務器資源,那會造成服務器數據被非法的篡改,所以這類請求是會被Spring security攔截的,在默認的情況下,spring security是啓用csrf 攔截功能的,這會造成,在跨域的情況下,post方式提交的請求都會被攔截無法被處理(包括合理的post請求),前端發起的post請求後端無法正常 處理,雖然保證了跨域的安全性,但影響了正常的使用,如果關閉csrf防護功能,雖然可以正常處理post請求,但是無法防範通過劫持session id的非法的post請求,所以spring security爲了正確的區別合法的post請求,採用了token的機制 。

​ 3)我在科普下:spring Security 3默認關閉csrf,Spring Security 4默認啓動了csrf

​ 4)如果不採用csrf,可禁用security的csrf ,如下

@Override
protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ………………
                .csrf().disable();
 }
## 4、重點解決問題 

我想開啓且有效,如下配置:

JAVA配置端該怎麼做

@Override
protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ………………
         .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
 }

###H5端怎麼做

說明下網上方法大致有三種,我這裏結合我們自己的平臺(SpringBoot[v1.5.12]+SpringSecurity[v4.2.5]+ Thymeleaf[v2.1.3])是這麼做的

//全局index頁面 不需要每個頁面 都寫
<meta name="_csrf_parameter" th:content="${_csrf.parameterName}" th:if="${_csrf}" />
<meta name="_csrf_header" th:content="${_csrf.headerName}" th:if="${_csrf}" />
<meta name="_csrf" th:content="${_csrf.token}" th:if="${_csrf}" />
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(header, token);
  }); 

單獨AJAX提交思考局部刷新

var headers = {};
    headers['X-CSRF-TOKEN'] = "[[${_csrf.token}]]"; 
    //參數
    headers: headers
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章