javascript
无状态Spring安全性第1部分:无状态CSRF保护
如今,隨著RESTful架構變得越來越標準,可能值得花一些時間重新考慮當前的安全方法。 在這個小系列的博客文章中,我們將探索一些以無狀態方式解決與Web相關的安全問題的相對較新的方法。 這第一篇文章是關于保護您的網站免受跨站請求偽造(CSRF)的攻擊。
總結:什么是跨站點偽造?
CSRF攻擊基于揮之不去的身份驗證Cookie。 在登錄或以其他方式標識為網站上的唯一訪問者之后,該網站可能會在瀏覽器中留下cookie。 如果不顯式注銷或以其他方式刪除此cookie,它可能會保持一段時間有效。
另一個站點可以通過使瀏覽器向受攻擊的站點發出(跨站點)請求來濫用此功能。 例如,包括一些用于在“ http://siteunderattack.com/changepassword?pw=hacked”標簽上進行POST的Javascript,將使瀏覽器發出該請求,并將對該域仍然有效的任何(身份驗證)cookie附加到該請求!
即使單源策略(SOP)不允許惡意站點訪問響應的任何部分。 從上面的示例中可以很明顯地看出,如果請求的URL在后臺觸發任何副作用(狀態更改),則損害已經完成。
常用方法
 常用的解決方案是引入所謂的共享秘密CSRF令牌的要求,并將其作為先前響應的一部分讓客戶端知道。 
 然后,對于任何有副作用的請求,客戶端都必須將其ping回服務器。 可以直接在表單中作為隱藏字段或作為自定義HTTP標頭完成此操作。 無論哪種方式,其他站點都無法成功產生包含正確CSRF令牌的請求,因為SOP阻止跨站點讀取來自服務器的響應。 這種方法的問題在于服務器需要記住會話中每個用戶的每個CSRF令牌的值。 
無狀態方法
1.切換到完整且設計正確的基于JSON的REST API。
單源策略僅允許跨站點的HEAD / GET和POST。 POST只能是以下啞劇類型之一:application / x-www-form-urlencoded,multipart / form-data或text / plain。 確實沒有JSON! 現在考慮到GET永遠不要在任何經過??適當設計的基于HTTP的API中觸發副作用,這讓您可以簡單地禁止任何非JSON POST / PUT / DELETE,一切都很好。 對于上傳文件(多部分/表單數據)的方案,仍然需要明確的CSRF保護。
2.檢查HTTP Referer標頭。
通過檢查仍然易受攻擊的場景(例如多部分/表單數據POST)的Referer標頭的存在和內容,可以進一步完善上述方法。 瀏覽器使用此標頭來指定觸發請求的確切頁面(url)。 這可以輕松地用于檢查站點的預期域。 請注意,如果選擇進行此類檢查,則在沒有標題的情況下,切勿允許請求。
3.客戶端生成的CSRF令牌。
讓客戶端在Cookie和自定義HTTP標頭中生成并發送相同的唯一秘密值。 考慮到僅允許網站為其自己的域讀取/寫入Cookie,因此只有真實網站才能在兩個標頭中發送相同的值。 使用這種方法,您的服務器要做的就是在每個請求無狀態的基礎上檢查兩個值是否相等!
實作
著眼于第三種基于顯式但基于無狀態CSRF令牌的安全性的方法,讓我們看看使用Spring Boot和Spring Security的代碼的外觀。
在Spring Boot中,您會獲得一些不錯的默認安全設置,您可以使用自己的配置適配器對其進行微調。 在這種情況下,所需要做的就是禁用默認的csrf行為并添加自己的StatelessCSRFFilter:
自定義CSRF保護
@EnableWebSecurity @Order(1) public class StatelessCSRFSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().addFilterBefore(new StatelessCSRFFilter(), CsrfFilter.class);} }這是StatelessCSRFFilter的實現:
自定義CSRF過濾器
public class StatelessCSRFFilter extends OncePerRequestFilter {private static final String CSRF_TOKEN = "CSRF-TOKEN";private static final String X_CSRF_TOKEN = "X-CSRF-TOKEN";private final RequestMatcher requireCsrfProtectionMatcher = new DefaultRequiresCsrfMatcher();private final AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {if (requireCsrfProtectionMatcher.matches(request)) {final String csrfTokenValue = request.getHeader(X_CSRF_TOKEN);final Cookie[] cookies = request.getCookies();String csrfCookieValue = null;if (cookies != null) {for (Cookie cookie : cookies) {if (cookie.getName().equals(CSRF_TOKEN)) {csrfCookieValue = cookie.getValue();}}}if (csrfTokenValue == null || !csrfTokenValue.equals(csrfCookieValue)) {accessDeniedHandler.handle(request, response, new AccessDeniedException("Missing or non-matching CSRF-token"));return;}}filterChain.doFilter(request, response);}public static final class DefaultRequiresCsrfMatcher implements RequestMatcher {private final Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");@Overridepublic boolean matches(HttpServletRequest request) {return !allowedMethods.matcher(request.getMethod()).matches();}} }不出所料,無狀態版本在兩個標頭值上只做一個簡單的equals()。
客戶端實施
客戶端實現也很簡單,尤其是在使用AngularJS時。 AngularJS已經提供了內置的CSRF令牌支持。 如果您告訴它要讀取的cookie,它將自動將其值發送到您選擇的自定義標頭中。 (瀏覽器負責發送cookie標頭本身。)
您可以按以下方式覆蓋AngularJS的默認名稱(XSRF而不是CSRF):
設置適當的令牌名稱
$http.defaults.xsrfHeaderName = 'X-CSRF-TOKEN'; $http.defaults.xsrfCookieName = 'CSRF-TOKEN';此外,如果您想為每個請求生成一個新的令牌值,則可以將自定義攔截器添加到$ httpProvider中,如下所示:
攔截器生成cookie
app.config(['$httpProvider', function($httpProvider) {//fancy random token, losely after https://gist.github.com/jed/982883function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e16]+1e16).replace(/[01]/g,b)};$httpProvider.interceptors.push(function() {return {'request': function(response) {// put a new random secret into our CSRF-TOKEN Cookie before each requestdocument.cookie = 'CSRF-TOKEN=' + b();return response;}};}); }]); 您可以在github上找到一個完整的可用示例。 
 確保已安裝gradle 2.0,并使用“ gradle build”和“ gradle run”簡單地運行它。 如果要像eclipse一樣在IDE中使用它,請使用“ gradle eclipse”,只需從IDE內導入并運行它即可(無需服務器)。 
免責聲明
有時,經典的CSRF令牌被錯誤地視為針對重播或暴力攻擊的解決方案。 此處列出的無狀態方法未涵蓋此類攻擊。 我個人認為這兩種類型的攻擊都應從另一個角度進行考慮,例如使用https和速率限制。 對于公開網站上的任何數據輸入,我倆都認為這是必須的!
翻譯自: https://www.javacodegeeks.com/2014/10/stateless-spring-security-part-1-stateless-csrf-protection.html
總結
以上是生活随笔為你收集整理的无状态Spring安全性第1部分:无状态CSRF保护的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 飞智ios怎么设置(ios飞智开启飞鼠功
 - 下一篇: gg泰拉瑞亚助手电脑版(gg助手泰拉瑞亚