spring security安全防禦

前言

xss攻擊(跨站腳本攻擊):攻擊者在頁面裏插入惡意腳本代碼,用戶瀏覽該頁面時,腳本代碼就會執行,達到攻擊者的目的。原理就是:攻擊者對含有漏洞的服務器注入惡意代碼,引誘用戶瀏覽受到攻擊的服務器,並打開相關頁面,執行惡意代碼。
xss攻擊方式:1、反射性攻擊,腳本代碼做爲url參數提交給服務器,服務器解析執行後,將腳本代碼返回給瀏覽器,最後瀏覽器解析執行攻擊代碼;2、存儲性攻擊,和發射性攻擊的區別是,腳本代碼存儲在服務器,下次在請求時,不用再提交腳本代碼。其中一個示例圖以下所示:
圖片描述css

CSRF攻擊:跨站請求僞造攻擊,CSRF是一種欺騙受害者提交惡意請求的攻擊,並劫持受害者的身份和特權,並以受害者的身份訪問未受權的信息和功能。序列圖以下所示:
圖片描述html

同步器Token

解決XSS攻擊和CSRF攻擊的一個推薦方法就是同步器Token,就是在post的請求中,增長一個token,每次請求到來,服務器都會驗證請求中的token和服務器指望的值是否一致,若是不一致,服務器將請求視爲非法的,整個過程的示例圖以下所示:
圖片描述ajax

在spring security中若是使用的是 @EnableWebMvcSecurity而不是@EnableWebSecurity,同步器Token是默認打開的,經過http().csrf().disable()能夠關閉同步器token功能。spring security發現token無效後,會返回一個403的訪問拒絕,不過能夠經過配置AccessDeniedHandler類處理InvalidCsrfTokenException異常來定製行爲。spring

spring security雖然默認是打開同步器token保護的,可是也提供了一個顯示打開的行爲即http().csrf(),同時須要在html的form表單中添加以「<input type="hidden"name="${_csrf.parameterName}" value="${_csrf.token}"/>」json

若是請求的是json或ajax請求,如何使用同步器token防禦那?
json請求的話,咱們能夠在header的元數據中添加token防禦,代碼以下所示:瀏覽器

<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
...
</head>

ajax請求的話,但是使用以下代碼:緩存

$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});

Synchronizer Token的常見問題
1.超時
由於token是存儲在httpsession中的,因此token存在超時的問題,一旦超時,則配置的accessDeniedHandler將接受一個異常,或者spring security直接拒絕訪問;
2.登陸
爲了防止僞造的登陸請求,在登陸的form中也須要添加token,而token又是存儲在HttpSession中,也就是說一旦發現token屬性,就會建立一個HttpSession,這和無狀態架構模式可能會產生一些衝突;
3.註銷
添加CSRF將更新LogoutFilter過濾器,使其只使用HTTP POST。這確保了註銷須要一個CSRF令牌,而且惡意用戶不能強制註銷您的用戶。也就是說,註銷再也不是一個get請求,而是一個post請求;安全

spring security支持的安全response header

spring security 支持的response header 包括:Cache-Control,Content-type options,HTTP Strict Transport Security,X-Frame-Options,X-XSS-Protection 若是你使用的是WebSecurityConfigurerAdapter 配置方式,則這些頭都是默認支持的,你能夠經過調用 http.header().disable()關閉這些缺省的頭。固然你也能夠單獨配置,可是若是你單獨配置的話,只有你配置的頭會起做用,其餘的頭都再也不默認支持了。下面分別來討論一下這些響應header的含義;服務器

Cache-Control
若是不加任何控制,瀏覽器一般會緩存你的認證相關信息,這在必定程度上會形成你的信息泄露,所以在默認狀況下,spring security會在響應頭裏加入緩存控制以下所示:session

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0

固然你也能夠經過 http.header().cacheControl()方法單獨打開緩存控制,你也能夠經過HttpServletResponse.setHeader(String,String)方法對特殊的響應作處理,從而確保css js 圖片可以合適地被緩存,在spring mvc中,能夠經過配置進行設置,下面的代碼對全部的資源都增長了緩存:

@EnableWebMvc
public class WebMvcConfiguration
     extends WebMvcConfigurerAdapter {
        @Override
        public void addResourceHandlers(
        ResourceHandlerRegistry registry) {
        registry
        .addResourceHandler("/resources/**")
        .addResourceLocations("/resources/")
        .setCachePeriod(3_155_6926);
        }
// ...
}

Content-type Options

歷史上不少不少瀏覽器都能能夠經過對請求類型的content進行嗅探,猜想請求類型,從而提升用戶體驗,可是這會帶來XSS攻擊。例若有些站點容許用戶向其提交有效的postScript腳本,並查看他。惡意用戶可能提交一個有效的js文件,並使用它執行XSS攻擊。spring security默認是禁止進行嗅探的。

HTTP Strict Transport Security
當你訪問一個站點是,例如www.baidu.com,省略了https協議,潛在的你會受到中間人攻擊,爲了減小這種狀況,就是告知瀏覽器,當你輸入某個地址時,應該使用https協議。如何讓瀏覽器該host是一個hsts站點那?其中一種方法就是,增長Strict-Transport-Security 到響應頭中,以下例所示:

Strict-Transport-Security: max-age=31536000 ; includeSubDomains

上述例子告知瀏覽器,該站點在一年內訪問都使用https協議,includeSubDomains說明該站點的子域名也使用https協議訪問。

X-frame-optiont

X-Frame-Options HTTP 響應頭是用來給瀏覽器指示容許一個頁面能否在 <frame>, <iframe> 或者 <object> 中展示的標記。網站可使用此功能,來確保本身網站的內容沒有被嵌到別人的網站中去,也從而避免了點擊劫持 (clickjacking) 的攻擊。
X-Frame-Options 有三個值: DENY 表示該頁面不容許在 frame 中展現,即使是在相同域名的頁面中嵌套也不容許。SAMEORIGIN 表示該頁面能夠在相同域名頁面的 frame 中展現。ALLOW-FROM uri表示該頁面能夠在指定來源的 frame 中展現。
Spring security默認是使用DENY,即拒絕在frame中展現,從而避免點擊劫持的攻擊,固然你也能夠進行單獨設置或對X-Frame-Option設置特殊的值。

Customer Header

Spring Security有一些機制,能夠方便地嚮應用程序添加更常見的安全頭。可是,它還提供了容許添加自定義頭的鉤子。有時,您但願將自定義安全頭插入到您的應用程序中,而該特性並無被支持。例如,您可能但願儘早支持內容安全策略,以確保資源只能從相同的源加載。因爲對內容安全策略的支持尚未最終肯定,瀏覽器使用兩個常見的擴展頭之一來實現這個特性。這意味着咱們將須要注入兩次策略。下面的代碼片斷中能夠看到一個頭的示例:

X-Content-Security-Policy: default-src 'self'
X-WebKit-CSP: default-src 'self'
@Override
protected void configure(HttpSecurity http) throws Exception {
        http.headers()
        .addHeaderWriter(
        new StaticHeadersWriter(
        "X-Content-Security-Policy",
        "default-src 'self'"))
        .addHeaderWriter(
        new StaticHeadersWriter(
        "X-WebKit-CSP",
        "default-src 'self'"));
}

當名稱空間或Java配置不支持您想要的頭部時,您能夠建立一個自定義的HeadersWriter實例,甚至能夠提供HeadersWriter的自定義實現。讓咱們看一個使用XFrameOptionsHeaderWriter的自定義實例的示例。也許您但願容許爲相同的起源構建內容框架。將策略屬性設置爲SAMEORIGIN很容易支持這一點:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.headers()
    .addHeaderWriter(
    new XFrameOptionsHeaderWriter(
    XFrameOptionsMode.SAMEORIGIN));
}

有時,您可能只想爲某些請求編寫一個header。例如,您可能只想保護您的登陸頁面。您可使用DelegatingRequestMatcherHeaderWriter類來這樣作。

@Override
protected void configure(HttpSecurity http) throws Exception {
    DelegatingRequestMatcherHeaderWriter headerWriter =
    new DelegatingRequestMatcherHeaderWriter(
    new AntPathRequestMatcher("/login"),
    new XFrameOptionsHeaderWriter());
    http.headers()
    .addHeaderWriter(headerWriter);
}
相關文章
相關標籤/搜索