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

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

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

服務器之家 - 編程語言 - Java教程 - SpringSecurity系列之請求防火墻默認已開啟

SpringSecurity系列之請求防火墻默認已開啟

2021-05-21 00:52江南一點雨 Java教程

使用 Spring Security 的好處就是,即使不了解這些攻擊,也不用擔心這些攻擊,因為 Spring Security 已經幫你做好防御工作了。今天我就來和大家聊一聊 Spring Security 中自帶的防火墻機制。

SpringSecurity系列之請求防火墻默認已開啟

之前有小伙伴表示,看 Spring Security 這么麻煩,不如自己寫一個 Filter 攔截請求,簡單實用。

自己寫當然也可以實現,但是大部分情況下,大家都不是專業的 Web 安全工程師,所以考慮問題也不過就是認證和授權,這兩個問題處理好了,似乎系統就很安全了。

其實不是這樣的!

各種各樣的 Web 攻擊每天都在發生,什么固定會話攻擊、csrf 攻擊等等,如果不了解這些攻擊,那么做出來的系統肯定也不能防御這些攻擊。

使用 Spring Security 的好處就是,即使不了解這些攻擊,也不用擔心這些攻擊,因為 Spring Security 已經幫你做好防御工作了。

我們常說相比于 Shiro,Spring Security 更加重量級,重量級有重量級的好處,比如功能全,安全管理更加完備。用了 Spring Security,你都不知道自己的系統有多安全!

今天我就來和大家聊一聊 Spring Security 中自帶的防火墻機制。

好了,不廢話了,我們來看文章。

1.HttpFirewall

 

在 Spring Security 中提供了一個 HttpFirewall,看名字就知道這是一個請求防火墻,它可以自動處理掉一些非法請求。

HttpFirewall 目前一共有兩個實現類:

SpringSecurity系列之請求防火墻默認已開啟

一個是嚴格模式的防火墻設置,還有一個默認防火墻設置。

DefaultHttpFirewall 的限制相對于 StrictHttpFirewall 要寬松一些,當然也意味著安全性不如 StrictHttpFirewall。

Spring Security 中默認使用的是 StrictHttpFirewall。

2.防護措施

 

那么 StrictHttpFirewall 都是從哪些方面來保護我們的應用呢?我們來挨個看下。

2.1 只允許白名單中的方法

首先,對于請求的方法,只允許白名單中的方法,也就是說,不是所有的 HTTP 請求方法都可以執行。

這點我們可以從 StrictHttpFirewall 的源碼中看出來:

  1. public class StrictHttpFirewall implements HttpFirewall { 
  2.  private Set<String> allowedHttpMethods = createDefaultAllowedHttpMethods(); 
  3.  private static Set<String> createDefaultAllowedHttpMethods() { 
  4.   Set<String> result = new HashSet<>(); 
  5.   result.add(HttpMethod.DELETE.name()); 
  6.   result.add(HttpMethod.GET.name()); 
  7.   result.add(HttpMethod.HEAD.name()); 
  8.   result.add(HttpMethod.OPTIONS.name()); 
  9.   result.add(HttpMethod.PATCH.name()); 
  10.   result.add(HttpMethod.POST.name()); 
  11.   result.add(HttpMethod.PUT.name()); 
  12.   return result; 
  13.  } 
  14.  private void rejectForbiddenHttpMethod(HttpServletRequest request) { 
  15.   if (this.allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) { 
  16.    return
  17.   } 
  18.   if (!this.allowedHttpMethods.contains(request.getMethod())) { 
  19.    throw new RequestRejectedException("The request was rejected because the HTTP method \"" + 
  20.      request.getMethod() + 
  21.      "\" was not included within the whitelist " + 
  22.      this.allowedHttpMethods); 
  23.   } 
  24.  } 

從這段代碼中我們看出來,你的 HTTP 請求方法必須是 DELETE、GET、HEAD、OPTIONS、PATCH、POST 以及 PUT 中的一個,請求才能發送成功,否則的話,就會拋出 RequestRejectedException 異常。

那如果你想發送其他 HTTP 請求方法,例如 TRACE ,該怎么辦呢?我們只需要自己重新提供一個 StrictHttpFirewall 實例即可,如下:

  1. @Bean 
  2. HttpFirewall httpFirewall() { 
  3.     StrictHttpFirewall firewall = new StrictHttpFirewall(); 
  4.     firewall.setUnsafeAllowAnyHttpMethod(true); 
  5.     return firewall; 

其中,setUnsafeAllowAnyHttpMethod 方法表示不做 HTTP 請求方法校驗,也就是什么方法都可以過。或者也可以通過 setAllowedHttpMethods 方法來重新定義可以通過的方法。

2.2 請求地址不能有分號

不知掉大家有沒有試過,如果你使用了 Spring Security,請求地址是不能有 ; 的,如果請求地址有 ; ,就會自動跳轉到如下頁面:

SpringSecurity系列之請求防火墻默認已開啟

可以看到,頁面的提示中已經說了,因為你的請求地址中包含 ;,所以請求失敗。

什么時候請求地址中會包含 ; 呢?不知道小伙伴們在使用 Shiro 的時候,有沒有注意到,如果你禁用了 Cookie,那么 jsessionid 就會出現在地址欄里,像下面這樣:

  1. http://localhost:8080/hello;jsessionid=xx 

這種傳遞 jsessionid 的方式實際上是非常不安全的(松哥后面的文章會和大家細聊這個問題),所以在 Spring Security 中,這種傳參方式默認就禁用了。

當然,如果你希望地址欄能夠被允許出現 ; ,那么可以按照如下方式設置:

  1. @Bean 
  2. HttpFirewall httpFirewall() { 
  3.     StrictHttpFirewall firewall = new StrictHttpFirewall(); 
  4.     firewall.setAllowSemicolon(true); 
  5.     return firewall; 

設置完成之后,再去訪問相同的接口,可以看到,此時雖然還是報錯,但是錯誤是 404 了,而不是一開始那個不允許 ; 的錯了。

SpringSecurity系列之請求防火墻默認已開啟

注意,在 URL 地址中,; 編碼之后是 %3b 或者 %3B,所以地址中同樣不能出現 %3b 或者 %3B

題外話

有的小伙伴可能不知道或者沒用過,Spring3.2 開始,帶來了一種全新的傳參方式 @MatrixVariable。

@MatrixVariable 是 Spring3.2 中帶來的功能,這種方式拓展了請求參數的傳遞格式,使得參數之間可以用 ; 隔開,這種傳參方式真是哪壺不開提哪壺。因為 Spring Security 默認就是禁止這種傳參方式,所以一般情況下,如果你需要使用 @MatrixVariable 來標記參數,就得在 Spring Security 中額外放行。

接下來我通過一個簡單的例子來和大家演示一下 @MatrixVariable 的用法。

我們新建一個 /hello 方法:

  1. @RequestMapping(value = "/hello/{id}"
  2. public void hello(@PathVariable Integer id,@MatrixVariable String name) { 
  3.     System.out.println("id = " + id); 
  4.     System.out.println("name = " + name); 

另外我們還需要配置一下 SpringMVC,使 ; 不要被自動移除了:

  1. @Configuration 
  2. public class WebMvcConfig extends WebMvcConfigurationSupport { 
  3.     @Override 
  4.     protected void configurePathMatch(PathMatchConfigurer configurer) { 
  5.         UrlPathHelper urlPathHelper = new UrlPathHelper(); 
  6.         urlPathHelper.setRemoveSemicolonContent(false); 
  7.         configurer.setUrlPathHelper(urlPathHelper); 
  8.     } 

然后啟動項目(注意,Spring Security 中也已經配置了允許 URL 中存在 ;),瀏覽器發送如下請求:

  1. http://localhost:8080/hello/123;name=javaboy 

控制臺打印信息如下:

  1. id = 123 
  2. name = javaboy 

可以看到,@MatrixVariable 注解已經生效了。

2.3 必須是標準化 URL

請求地址必須是標準化 URL。

什么是標準化 URL?標準化 URL 主要從四個方面來判斷,我們來看下源碼:

StrictHttpFirewall#isNormalized:

  1. private static boolean isNormalized(HttpServletRequest request) { 
  2.  if (!isNormalized(request.getRequestURI())) { 
  3.   return false
  4.  } 
  5.  if (!isNormalized(request.getContextPath())) { 
  6.   return false
  7.  } 
  8.  if (!isNormalized(request.getServletPath())) { 
  9.   return false
  10.  } 
  11.  if (!isNormalized(request.getPathInfo())) { 
  12.   return false
  13.  } 
  14.  return true

getRequestURI 就是獲取請求協議之外的字符;getContextPath 是獲取上下文路徑,相當于是 project 的名字;getServletPath 這個就是請求的 servlet 路徑,getPathInfo 則是除過 contextPath 和 servletPath 之后剩余的部分。

這四種路徑中,都不能包含如下字符串:

  1. "./""/../" or "/." 

2.4 必須是可打印的 ASCII 字符

如果請求地址中包含不可打印的 ASCII 字符,請求則會被拒絕,我們可以從源碼中看出端倪:

StrictHttpFirewall#containsOnlyPrintableAsciiCharacters

  1. private static boolean containsOnlyPrintableAsciiCharacters(String uri) { 
  2.  int length = uri.length(); 
  3.  for (int i = 0; i < length; i++) { 
  4.   char c = uri.charAt(i); 
  5.   if (c < '\u0020' || c > '\u007e') { 
  6.    return false
  7.   } 
  8.  } 
  9.  return true

2.5 雙斜杠不被允許

如果請求地址中出現雙斜杠,這個請求也將被拒絕。雙斜杠 // 使用 URL 地址編碼之后,是 %2F%2F,其中 F 大小寫無所謂,所以請求地址中也能不出現 "%2f%2f", "%2f%2F", "%2F%2f", "%2F%2F"。

如果你希望請求地址中可以出現 // ,可以按照如下方式配置:

  1. @Bean 
  2. HttpFirewall httpFirewall() { 
  3.     StrictHttpFirewall firewall = new StrictHttpFirewall(); 
  4.     firewall.setAllowUrlEncodedDoubleSlash(true); 
  5.     return firewall; 

2.6 % 不被允許

如果請求地址中出現 %,這個請求也將被拒絕。URL 編碼后的 % 是 %25,所以 %25 也不能出現在 URL 地址中。

如果希望請求地址中可以出現 %,可以按照如下方式修改:

  1. @Bean 
  2. HttpFirewall httpFirewall() { 
  3.     StrictHttpFirewall firewall = new StrictHttpFirewall(); 
  4.     firewall.setAllowUrlEncodedPercent(true); 
  5.     return firewall; 

2.7 正反斜杠不被允許

如果請求地址中包含斜杠編碼后的字符 %2F 或者 %2f ,則請求將被拒絕。

如果請求地址中包含反斜杠 \ 或者反斜杠編碼后的字符 %5C 或者 %5c ,則請求將被拒絕。

如果希望去掉如上兩條限制,可以按照如下方式來配置:

  1. @Bean 
  2. HttpFirewall httpFirewall() { 
  3.     StrictHttpFirewall firewall = new StrictHttpFirewall(); 
  4.     firewall.setAllowBackSlash(true); 
  5.     firewall.setAllowUrlEncodedSlash(true); 
  6.     return firewall; 

2.8 . 不被允許

如果請求地址中存在 . 編碼之后的字符 %2e、%2E,則請求將被拒絕。

如需支持,按照如下方式進行配置:

  1. @Bean 
  2. HttpFirewall httpFirewall() { 
  3.     StrictHttpFirewall firewall = new StrictHttpFirewall(); 
  4.     firewall.setAllowUrlEncodedPeriod(true); 
  5.     return firewall; 

2.9 小結

需要強調一點,上面所說的這些限制,都是針對請求的 requestURI 進行的限制,而不是針對請求參數。例如你的請求格式是:

  1. http://localhost:8080/hello?param=aa%2ebb 

那么 2.7 小節說的限制和你沒關系。

這個大家從 StrictHttpFirewall 源碼中很容易看到:

  1. public class StrictHttpFirewall implements HttpFirewall { 
  2.  @Override 
  3.  public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { 
  4.   rejectForbiddenHttpMethod(request); 
  5.   rejectedBlacklistedUrls(request); 
  6.   rejectedUntrustedHosts(request); 
  7.  
  8.   if (!isNormalized(request)) { 
  9.    throw new RequestRejectedException("The request was rejected because the URL was not normalized."); 
  10.   } 
  11.  
  12.   String requestUri = request.getRequestURI(); 
  13.   if (!containsOnlyPrintableAsciiCharacters(requestUri)) { 
  14.    throw new RequestRejectedException("The requestURI was rejected because it can only contain printable ASCII characters."); 
  15.   } 
  16.   return new FirewalledRequest(request) { 
  17.    @Override 
  18.    public void reset() { 
  19.    } 
  20.   }; 
  21.  } 
  22.  private void rejectedBlacklistedUrls(HttpServletRequest request) { 
  23.   for (String forbidden : this.encodedUrlBlacklist) { 
  24.    if (encodedUrlContains(request, forbidden)) { 
  25.     throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\""); 
  26.    } 
  27.   } 
  28.   for (String forbidden : this.decodedUrlBlacklist) { 
  29.    if (decodedUrlContains(request, forbidden)) { 
  30.     throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\""); 
  31.    } 
  32.   } 
  33.  } 
  34.  private static boolean encodedUrlContains(HttpServletRequest request, String value) { 
  35.   if (valueContains(request.getContextPath(), value)) { 
  36.    return true
  37.   } 
  38.   return valueContains(request.getRequestURI(), value); 
  39.  } 
  40.  
  41.  private static boolean decodedUrlContains(HttpServletRequest request, String value) { 
  42.   if (valueContains(request.getServletPath(), value)) { 
  43.    return true
  44.   } 
  45.   if (valueContains(request.getPathInfo(), value)) { 
  46.    return true
  47.   } 
  48.   return false
  49.  } 
  50.  private static boolean valueContains(String value, String contains) { 
  51.   return value != null && value.contains(contains); 
  52.  } 

rejectedBlacklistedUrls 方法就是校驗 URL 的,該方法邏輯很簡單,我就不再贅述了。

注意:雖然我們可以手動修改 Spring Security 中的這些限制,但是松哥不建議大家做任何修改,每一條限制都有它的原由,每放開一個限制,就會帶來未知的安全風險。后面松哥在和大家分享 Web 中的安全攻擊時,也會再次提到這些限制的作用,請小伙伴們保持關注哦。

3.總結

 

沒想到吧?Spring Security 竟然為你做了這么多事情!正好應了那句雞湯:你所謂的歲月靜好,不過是有人在替你負重前行。

原文鏈接:https://mp.weixin.qq.com/s/dBW8ney9HQSg6p2FC9AM0Q

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 性一交一无一伦一精一品 | 男人天堂999 | 亚洲精品中文字幕久久久久久 | 国产精品视频免费视频 | 我把校花黑色蕾丝胸罩脱了 | 欧美日韩看看2015永久免费 | 男人女人性生活视频 | 日本xx高清视频免费观看 | 国产a片毛片 | 羞羞答答免费人成黄页在线观看国产 | 美女被吸乳老师羞羞漫画 | 贰佰麻豆剧果冻传媒一二三区 | 秋霞一级 | 15同性同志18 | 国产在视频 | 男女做性视频 | 99精品视频在线观看免费播放 | 经典三级四虎在线观看 | 97色伦亚洲自偷 | 操骚0| 亚洲妇熟xxxxx妇色黄 | 四虎一区| 免费看一级毛片 | 国产亚洲精品美女久久久 | 欧美a一级片 | 色婷婷婷丁香亚洲综合不卡 | 大象传媒1234区 | 色老板在线免费观看 | 亚洲精品久久玖玖玖玖 | mm131亚洲| 久久视热频国产这里只有精品23 | 日韩高清无砖砖区2022 | www.尤物在线 | 国产精品视频一区二区三区w | 福利片福利一区二区三区 | 青草网址 | 国产99精品成人免费视频 | 国产suv精品 | 日本中文字幕一区二区有码在线 | 亚洲高清无码在线 视频 | 国产精品一区久久精品 |