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

file

1、什麼是CSRF

不少朋友在學習Spring Security的時候,會將CORS(跨站資源共享)和CSRF(跨站請求僞造)弄混,覺得兩者是一回事。其實不是,先解釋一下:前端

  • CORS(跨站資源共享)是局部打破同源策略的限制,使在必定規則下HTTP請求能夠突破瀏覽器限制,實現跨站訪問。
  • CSRF是一種網絡攻擊方式,也能夠說是一種安全漏洞,這種安全漏洞在web開發中普遍存在。

當咱們使用Spring Security的時候,這種CSRF漏洞默認的被防護掉了。可是你會發如今跨域請求的狀況下,咱們的POST、DELETE、PUT等HTTP請求方式失效了。因此在筆者以前的文章中,咱們使用http.csrf.disable()暫時關閉掉了CSRF的防護功能,可是這樣是不安全的,那麼怎麼樣纔是正確的作法呢?就是本文須要向你們介紹的內容。web

2、CSRF的攻擊方式

一般的CSRF攻擊方式以下:ajax

  • 你登陸了網站A,攻擊者向你的網站A帳戶發送留言、僞造嵌入頁面,帶有危險操做連接。
  • 當你在登陸狀態下點擊了攻擊者的鏈接,所以該連接對你網站A的帳戶進行了操做。
  • 這個操做是你在網站A中主動發出的,而且也是針對網站A的HTTP連接請求,同源策略沒法限制該請求。

3、如何防護CSRF攻擊

  • 爲系統中的每個鏈接請求加上一個token,這個token是隨機的,服務端對該token進行驗證。破壞者在留言或者僞造嵌入頁面的時候,沒法預先判斷CSRF token的值是什麼,因此當服務端校驗CSRF token的時候也就沒法經過。因此這種方法在必定程度上是靠譜的。
  • 可是若是你的電腦中毒,網絡信息被劫持使用token的方法仍然不安全。因此沒有絕對的安全,道高一次魔高一丈。做爲開發者,咱們就作到咱們應該作到的。
  • 跳轉提示:當用戶不當心點擊了第三方鏈接,合格的應用應該提示用戶相關的風險!由用戶本身確認是否真的要跳轉或者執行第三方鏈接,或者就乾脆不讓非可信鏈接在留言區等地方存在。

4、Spring Security的CSRF token攻擊防禦

首先,咱們要先開啓防禦功能,在用戶登錄操做以後,生成的CSRF Token就保存在cookies中。spring

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。後端

5、前端請求攜帶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}">複製代碼

期待您的關注

相關文章
相關標籤/搜索