成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

安全 應用安全
各種各樣的 Web 攻擊每天都在發(fā)生,什么固定會話攻擊、csrf 攻擊等等,如果不了解這些攻擊,那么做出來的系統(tǒng)肯定也不能防御這些攻擊。

[[400681]]

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

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

其實不是這樣的!

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

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

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

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

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

1.HttpFirewall

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

HttpFirewall 目前一共有兩個實現(xiàn)類:

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

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

Spring Security 中默認使用的是 StrictHttpFirewall。

2.防護措施

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

2.1 只允許白名單中的方法

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

這點我們可以從 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 中的一個,請求才能發(fā)送成功,否則的話,就會拋出 RequestRejectedException 異常。

那如果你想發(fā)送其他 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,請求地址是不能有 ; 的,如果請求地址有 ; ,就會自動跳轉到如下頁面:

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

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

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

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

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

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

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

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

題外話

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

@MatrixVariable 是 Spring3.2 中帶來的功能,這種方式拓展了請求參數(shù)的傳遞格式,使得參數(shù)之間可以用 ; 隔開,這種傳參方式真是哪壺不開提哪壺。因為 Spring Security 默認就是禁止這種傳參方式,所以一般情況下,如果你需要使用 @MatrixVariable 來標記參數(shù),就得在 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 中也已經(jīng)配置了允許 URL 中存在 ;),瀏覽器發(fā)送如下請求:

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

控制臺打印信息如下:

  1. id = 123 
  2. name = javaboy 

可以看到,@MatrixVariable 注解已經(jīng)生效了。

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 就是獲取請求協(xié)議之外的字符;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 雙斜杠不被允許

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

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

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

2.6 % 不被允許

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

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

  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 進行的限制,而不是針對請求參數(shù)。例如你的請求格式是:

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

那么 2.7 小節(jié)說的限制和你沒關系。

這個大家從 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 竟然為你做了這么多事情!正好應了那句雞湯:你所謂的歲月靜好,不過是有人在替你負重前行。

責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2011-04-28 19:51:03

2011-03-15 09:10:42

Linux防火墻Iptables

2010-12-21 18:04:26

2010-07-01 10:29:08

2010-12-08 09:29:27

下一代防火墻

2010-09-14 13:08:52

2011-02-15 10:44:27

2011-06-27 13:31:21

2010-05-24 17:49:56

2011-06-29 10:29:55

2011-08-18 10:22:44

2021-06-25 18:31:37

云防火墻

2013-07-04 10:16:24

2010-09-09 17:22:36

2009-09-24 13:53:53

2011-03-25 11:18:51

2014-02-27 13:46:32

華為防火墻USG9580

2020-02-20 11:03:05

云防火墻安全運維

2009-08-24 08:37:52

Windows 7防火墻

2009-02-22 09:30:24

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲人成人一区二区在线观看 | av一二三四 | 久青草影院 | 亚洲精品乱码久久久久久黑人 | 天天操天天射天天舔 | 亚洲国产精品成人久久久 | 中文无吗 | 日本一区二区在线视频 | 中文字幕精品一区 | 久久中文字幕一区 | 国产一级一片免费播放 | 一区二区在线不卡 | 欧美精品二区三区 | 亚洲精品视频一区 | 亚洲欧洲在线看 | 超碰日本 | 国产精品欧美一区二区三区 | 久久免费视频观看 | 欧美午夜一区 | 日朝毛片 | 久久激情网 | 久久四虎| 国产精品av久久久久久毛片 | 精品亚洲一区二区三区四区五区 | 欧美11一13sex性hd | www.狠狠干 | 91国内在线观看 | 国户精品久久久久久久久久久不卡 | 羞羞涩涩在线观看 | 午夜色婷婷 | 亚洲视频二| 日韩二| 久久久视频在线 | 久久精品91久久久久久再现 | 亚洲v日韩v综合v精品v | 一级看片| 天堂色| 亚洲综合一区二区三区 | 狠狠色综合久久丁香婷婷 | 99pao成人国产永久免费视频 | 91人人澡人人爽 |