一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - 詳解利用spring-security解決CSRF問題

詳解利用spring-security解決CSRF問題

2021-04-21 14:52I,Frankenstein Java教程

這篇文章主要介紹了詳解利用spring-security解決CSRF問題,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

CSRF介紹

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。

具體SCRF的介紹和攻擊方式請參看百度百科的介紹和一位大牛的分析:
CSRF百度百科

配置步驟

1.依賴jar包

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<properties>
    <spring.security.version>4.2.2.RELEASE</spring.security.version>
  </properties>
<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>${spring.security.version}</version>
      </dependency>
 
      <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>${spring.security.version}</version>
      </dependency>
 
      <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${spring.security.version}</version>
      </dependency>

2.web.xml配置

?
1
2
3
4
5
6
7
8
9
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
 
  <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

3.Spring配置文件配置

?
1
2
3
4
5
6
7
8
<bean id="csrfSecurityRequestMatcher" class="com.xxx.CsrfSecurityRequestMatcher"></bean>
 
  <security:http auto-config="true" use-expressions="true">
    <security:headers>
      <security:frame-options disabled="true"/>
    </security:headers>
    <security:csrf request-matcher-ref="csrfSecurityRequestMatcher" />
  </security:http>

4.自定義RequestMatcher的實現類CsrfSecurityRequestMatcher

這個類被用來自定義哪些請求是不需要進行攔截過濾的。如果配置csrf,所有http請求都被會CsrfFilter攔截,而CsrfFilter中有一個私有類DefaultRequiresCsrfMatcher。

源碼1:DefaultRequiresCsrfMatcher類

?
1
2
3
4
5
6
7
8
9
10
11
private static final class DefaultRequiresCsrfMatcher implements RequestMatcher {
    private final HashSet<String> allowedMethods;
 
    private DefaultRequiresCsrfMatcher() {
      this.allowedMethods = new HashSet(Arrays.asList(new String[]{"GET", "HEAD", "TRACE", "OPTIONS"}));
    }
 
    public boolean matches(HttpServletRequest request) {
      return !this.allowedMethods.contains(request.getMethod());
    }
  }

從這段源碼可以發現,POST方法被排除在外了,也就是說只有GET|HEAD|TRACE|OPTIONS這4類方法會被放行,其它Method的http請求,都要驗證_csrf的token是否正確,而通常post方式調用rest接口服務時,又沒有_csrf的token,所以會導致我們的rest接口調用失敗,我們需要自定義一個類對該類型接口進行放行。來看下我們自定義的過濾器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class CsrfSecurityRequestMatcher implements RequestMatcher {
  private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
  private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("^/rest/.*", null);
 
  @Override
  public boolean matches(HttpServletRequest request) {
    if(allowedMethods.matcher(request.getMethod()).matches()){
      return false;
    }
 
    return !unprotectedMatcher.matches(request);
  }
}

說明:一般我們定義的rest接口服務,都帶上 /rest/ ,所以如果你的項目中不是使用的這種,或者項目中沒有rest服務,這個類完全可以省略的。

5.post請求配置

一般我們的項目中都有一個通用的jsp文件,就是每個頁面都會引用的,所以我們可以在通用文件中做如下配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
 
<script>
 
  var token = $("meta[name='_csrf']").attr("content");
  var header = $("meta[name='_csrf_header']").attr("content");
  $.ajaxSetup({
    beforeSend: function (xhr) {
      if(header && token ){
        xhr.setRequestHeader(header, token);
      }
    }}
  );
</script>

$.ajaxSetup的意思就是給我們所有的請求都加上這個header和token,或者放到form表單中。注意,_csrf這個要與spring security的配置文件中的配置相匹配,默認為_csrf。

源碼解析

我們知道,既然配置了csrf,所有的http請求都會被CsrfFilter攔截到,所以看下CsrfFilter的源碼就對原理一目了然了。這里我們只看具體過濾的方法即可:

源碼3:CsrfFilter的doFilterInternal方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    request.setAttribute(HttpServletResponse.class.getName(), response);
    CsrfToken csrfToken = this.tokenRepository.loadToken(request);
    boolean missingToken = csrfToken == null;
    if(missingToken) {//如果token為空,說明第一次訪問,生成一個token對象
      csrfToken = this.tokenRepository.generateToken(request);
      this.tokenRepository.saveToken(csrfToken, request, response);
    }
 
    request.setAttribute(CsrfToken.class.getName(), csrfToken);
    //把token對象放到request中,注意這里key是csrfToken.getParameterName()= _csrf,所以我們頁面上才那么寫死。
    request.setAttribute(csrfToken.getParameterName(), csrfToken);
     
    //這個macher就是我們在Spring配置文件中自定義的過濾器,也就是GET,HEAD, TRACE, OPTIONS和我們的rest都不處理
    if(!this.requireCsrfProtectionMatcher.matches(request)) {
      filterChain.doFilter(request, response);
    } else {
      String actualToken = request.getHeader(csrfToken.getHeaderName());
      if(actualToken == null) {
        actualToken = request.getParameter(csrfToken.getParameterName());
      }
 
      if(!csrfToken.getToken().equals(actualToken)) {
        if(this.logger.isDebugEnabled()) {
          this.logger.debug("Invalid CSRF token found for " + UrlUtils.buildFullRequestUrl(request));
        }
 
        if(missingToken) {
          this.accessDeniedHandler.handle(request, response, new MissingCsrfTokenException(actualToken));
        } else {
          this.accessDeniedHandler.handle(request, response, new InvalidCsrfTokenException(csrfToken, actualToken));
        }
 
      } else {
        filterChain.doFilter(request, response);
      }
    }
  }

從源碼中可以看到,通過我們自定義的過濾器以外的post請求都需要進行token驗證。

本來呢,是想截圖弄個案例上去的,然后通過斷點看看頁面和后臺的傳值情況....不過,我這里沒法上傳圖片抓狂。好吧,就總結這么多吧!如果有寫的不對的或者有其他問題可以留言交流。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/u013185616/article/details/70446392

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美人交性视频在线香蕉 | 果冻传媒在线播放观看228集 | 99亚洲自拍 | 亚洲欧美精品久久 | 456在线观看 | 二区免费视频 | 牛牛影院成人免费网页 | 国产精品网页 | 色中文网 | 调教女高中生第3部分 | 嫩草在线视频www免费观看 | 四虎一区 | 久久不射视频 | 91理论片午午伦夜理片久久 | 国产精品久久久久a影院 | 精品一久久香蕉国产线看观 | 欧美日韩精品乱国产 | 狠狠干2017 | 亚洲2023无矿砖码砖区 | 成人看的羞羞视频免费观看 | 国产欧美日韩不卡 | 44444色视频在线观看 | 高清在线一区二区 | 精品福利一区 | 邪恶肉肉全彩色无遮盖 | 好 舒服 好 粗 好硬免费视频 | 果冻传媒和91制片厂网站软件 | 国内精品久久久久久野外 | a级片欧美 | kk4444了欧美 | 女教师被学生糟蹋三天 | 日本人泡妞18xxⅹ | 久久青草免费91线频观看站街 | 国产偷窥| 扒开尿口| 国产va免费精品高清在线 | 成版人快猫永久破解版 | aaa黄色| 国产乱子伦在线观看不卡 | 日韩高清无砖砖区2022 | 无码中文字幕av免费放 |