国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

SpringSecurity系列之請求默認已開(kāi)啟防火墻的示例分

發(fā)布時(shí)間:2021-09-14 11:25 來(lái)源:億速云 閱讀:0 作者:柒染 欄目: 網(wǎng)絡(luò )安全

這篇文章給大家介紹SpringSecurity系列之請求默認已開(kāi)啟防火墻的示例分析,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

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

其實(shí)不是這樣的!

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

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

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

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

好了,不廢話(huà)了,我們來(lái)看文章。

1.HttpFirewall

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

HttpFirewall 目前一共有兩個(gè)實(shí)現類(lèi):

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

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

Spring Security 中默認使用的是 StrictHttpFirewall。

2.防護措施

那么 StrictHttpFirewall 都是從哪些方面來(lái)保護我們的應用呢?我們來(lái)挨個(gè)看下。

2.1 只允許白名單中的方法

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

這點(diǎn)我們可以從 StrictHttpFirewall 的源碼中看出來(lái):

public class StrictHttpFirewall implements HttpFirewall {  private Set<String> allowedHttpMethods = createDefaultAllowedHttpMethods();  private static Set<String> createDefaultAllowedHttpMethods() {   Set<String> result = new HashSet<>();   result.add(HttpMethod.DELETE.name());   result.add(HttpMethod.GET.name());   result.add(HttpMethod.HEAD.name());   result.add(HttpMethod.OPTIONS.name());   result.add(HttpMethod.PATCH.name());   result.add(HttpMethod.POST.name());   result.add(HttpMethod.PUT.name());   return result;  }  private void rejectForbiddenHttpMethod(HttpServletRequest request) {   if (this.allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {    return;   }   if (!this.allowedHttpMethods.contains(request.getMethod())) {    throw new RequestRejectedException("The request was rejected because the HTTP method \"" +      request.getMethod() +      "\" was not included within the whitelist " +      this.allowedHttpMethods);   }  } }

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

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

@Bean HttpFirewall httpFirewall() {     StrictHttpFirewall firewall = new StrictHttpFirewall();     firewall.setUnsafeAllowAnyHttpMethod(true);     return firewall; }

其中,setUnsafeAllowAnyHttpMethod 方法表示不做 HTTP 請求方法校驗,也就是什么方法都可以過(guò)?;蛘咭部梢酝ㄟ^(guò)  setAllowedHttpMethods 方法來(lái)重新定義可以通過(guò)的方法。

2.2 請求地址不能有分號

不知掉大家有沒(méi)有試過(guò),如果你使用了 Spring Security,請求地址是不能有 ; 的,如果請求地址有 ; ,就會(huì )自動(dòng)跳轉到如下頁(yè)面:

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

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

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

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

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

@Bean HttpFirewall httpFirewall() {     StrictHttpFirewall firewall = new StrictHttpFirewall();     firewall.setAllowSemicolon(true);     return firewall; }

設置完成之后,再去訪(fǎng)問(wèn)相同的接口,可以看到,此時(shí)雖然還是報錯,但是錯誤是 404 了,而不是一開(kāi)始那個(gè)不允許 ; 的錯了。

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

題外話(huà)

有的小伙伴可能不知道或者沒(méi)用過(guò),Spring3.2 開(kāi)始,帶來(lái)了一種全新的傳參方式 @MatrixVariable。

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

接下來(lái)我通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)和大家演示一下 @MatrixVariable 的用法。

我們新建一個(gè) /hello 方法:

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

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

@Configuration public class WebMvcConfig extends WebMvcConfigurationSupport {     @Override     protected void configurePathMatch(PathMatchConfigurer configurer) {         UrlPathHelper urlPathHelper = new UrlPathHelper();         urlPathHelper.setRemoveSemicolonContent(false);         configurer.setUrlPathHelper(urlPathHelper);     } }

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

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

控制臺打印信息如下:

id = 123 name = javaboy

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

2.3 必須是標準化 URL

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

什么是標準化 URL?標準化 URL 主要從四個(gè)方面來(lái)判斷,我們來(lái)看下源碼:

StrictHttpFirewall#isNormalized:

private static boolean isNormalized(HttpServletRequest request) {  if (!isNormalized(request.getRequestURI())) {   return false;  }  if (!isNormalized(request.getContextPath())) {   return false;  }  if (!isNormalized(request.getServletPath())) {   return false;  }  if (!isNormalized(request.getPathInfo())) {   return false;  }  return true; }

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

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

"./", "/../" or "/."

2.4 必須是可打印的 ASCII 字符

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

StrictHttpFirewall#containsOnlyPrintableAsciiCharacters

private static boolean containsOnlyPrintableAsciiCharacters(String uri) {  int length = uri.length();  for (int i = 0; i < length; i++) {   char c = uri.charAt(i);   if (c < '\u0020' || c > '\u007e') {    return false;   }  }  return true; }

2.5 雙斜杠不被允許

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

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

@Bean HttpFirewall httpFirewall() {     StrictHttpFirewall firewall = new StrictHttpFirewall();     firewall.setAllowUrlEncodedDoubleSlash(true);     return firewall; }

2.6 % 不被允許

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

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

@Bean HttpFirewall httpFirewall() {     StrictHttpFirewall firewall = new StrictHttpFirewall();     firewall.setAllowUrlEncodedPercent(true);     return firewall; }

2.7 正反斜杠不被允許

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

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

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

@Bean HttpFirewall httpFirewall() {     StrictHttpFirewall firewall = new StrictHttpFirewall();     firewall.setAllowBackSlash(true);     firewall.setAllowUrlEncodedSlash(true);     return firewall; }

2.8 . 不被允許

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

如需支持,按照如下方式進(jìn)行配置:

@Bean HttpFirewall httpFirewall() {     StrictHttpFirewall firewall = new StrictHttpFirewall();     firewall.setAllowUrlEncodedPeriod(true);     return firewall; }

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

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

那么 2.7 小節說(shuō)的限制和你沒(méi)關(guān)系。

這個(gè)大家從 StrictHttpFirewall 源碼中很容易看到:

public class StrictHttpFirewall implements HttpFirewall {  @Override  public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {   rejectForbiddenHttpMethod(request);   rejectedBlacklistedUrls(request);   rejectedUntrustedHosts(request);    if (!isNormalized(request)) {    throw new RequestRejectedException("The request was rejected because the URL was not normalized.");   }    String requestUri = request.getRequestURI();   if (!containsOnlyPrintableAsciiCharacters(requestUri)) {    throw new RequestRejectedException("The requestURI was rejected because it can only contain printable ASCII characters.");   }   return new FirewalledRequest(request) {    @Override    public void reset() {    }   };  }  private void rejectedBlacklistedUrls(HttpServletRequest request) {   for (String forbidden : this.encodedUrlBlacklist) {    if (encodedUrlContains(request, forbidden)) {     throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\"");    }   }   for (String forbidden : this.decodedUrlBlacklist) {    if (decodedUrlContains(request, forbidden)) {     throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\"");    }   }  }  private static boolean encodedUrlContains(HttpServletRequest request, String value) {   if (valueContains(request.getContextPath(), value)) {    return true;   }   return valueContains(request.getRequestURI(), value);  }   private static boolean decodedUrlContains(HttpServletRequest request, String value) {   if (valueContains(request.getServletPath(), value)) {    return true;   }   if (valueContains(request.getPathInfo(), value)) {    return true;   }   return false;  }  private static boolean valueContains(String value, String contains) {   return value != null && value.contains(contains);  } }

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

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

午夜福利一区二区三区在线观看| 少妇高潮太爽了在线观看| 麻花星空无限传媒制作有限公司| 天堂А√在线中文在线新版| 国产精品亚洲专区无码不卡| 每日更新在线观看AV|