1. 程式人生 > >SpringSecurity框架下實現CSRF跨站攻擊防禦

SpringSecurity框架下實現CSRF跨站攻擊防禦

一、什麼是CSRF

很多朋友在學習Spring Security的時候,會將CORS(跨站資源共享)和CSRF(跨站請求偽造)弄混,以為二者是一回事。其實不是,先解釋一下:

  • CORS(跨站資源共享)是區域性打破同源策略的限制,使在一定規則下HTTP請求可以突破瀏覽器限制,實現跨站訪問。
  • CSRF是一種網路攻擊方式,也可以說是一種安全漏洞,這種安全漏洞在web開發中廣泛存在。

當我們使用Spring Security的時候,這種CSRF漏洞預設的被防禦掉了。但是你會發現在跨域請求的情況下,我們的POST、DELETE、PUT等HTTP請求方式失效了。所以在筆者之前的文章中,我們使用http.csrf.disable()

暫時關閉掉了CSRF的防禦功能,但是這樣是不安全的,那麼怎麼樣才是正確的做法呢?就是本文需要向大家介紹的內容。

二、CSRF的攻擊方式

通常的CSRF攻擊方式如下:

  • 你登入了網站A,攻擊者向你的網站A賬戶傳送留言、偽造嵌入頁面,帶有危險操作連結。
  • 當你在登入狀態下點選了攻擊者的連線,因此該連結對你網站A的賬戶進行了操作。
  • 這個操作是你在網站A中主動發出的,並且也是針對網站A的HTTP連結請求,同源策略無法限制該請求。

三、如何防禦CSRF攻擊

  • 為系統中的每一個連線請求加上一個token,這個token是隨機的,服務端對該token進行驗證。破壞者在留言或者偽造嵌入頁面的時候,無法預先判斷CSRF token的值是什麼,所以當服務端校驗CSRF token的時候也就無法通過。所以這種方法在一定程度上是靠譜的。
  • 但是如果你的電腦中毒,網路資訊被劫持使用token的方法仍然不安全。所以沒有絕對的安全,道高一次魔高一丈。作為開發者,我們就做到我們應該做到的。
  • 跳轉提示:當用戶不小心點選了第三方連線,合格的應用應該提示使用者相關的風險!由使用者自己確認是否真的要跳轉或者執行第三方連線,或者就乾脆不讓非可信連線在留言區等地方存在。

四、Spring Security的CSRF token攻擊防護

首先,我們要先開啟防護功能,在使用者登陸操作之後,生成的CSRF Token就儲存在cookies中。

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .ignoringAntMatchers("/authentication");
        .and()
        ...
    }
}
  • 使用CookieCsrfTokenRepository生成CSRF Token放入cookie,並設定cookie的HttpOnly=false,允許js讀取該cookie。
  • 使用ignoringAntMatchers開放一些不需要進行CSRF防護的訪問路徑,比如:登入授權。

至此,我們生成了CSRF token儲存在了cookies中,瀏覽器向服務端傳送的HTTP請求,都要將CSRF token帶上,服務端校驗通過才能正確的響應。這個校驗的過程並不需要我們自己寫程式碼實現,Spring Security會自動處理。但是我們需要關注前端程式碼,如何正確的攜帶CSRF token。

五、前端請求攜帶CSRF Token的方式

在thymeleaf模板中可以使用如下方式,在傳送HTTP請求的時候攜帶CSRF Token。如果是前後端分離的應用,或者其他模板引擎,酌情從cookies中獲取CSRF Toekn。

5.1.在Header中攜帶CSRF token

var headers = {};
headers['X-CSRF-TOKEN'] = "${_csrf.token}";
$.ajax({    
    headers: headers,    
});

5.2.直接作為引數提交。

$.ajax({    
    data: {      
       "_csrf": "${_csrf.token}"        
    }
});

5.3.form表單的隱藏欄位

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">

期待您的關注

  • 向您推薦博主的系列文件:《手摸手教您學習SpringBoot系列-16章97節》
  • 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格。