第一部分.csrf問題會致使ajax請求失敗,緣由是沒有驗證csrf的token。具體流程是啓用csrf後,全部http請求都被會CsrfFilter攔截,而CsrfFilter中有一個私有類DefaultRequiresCsrfMatcher ,在這個類裏面,POST方法被排除在外了,也就是說只有GET|HEAD|TRACE|OPTIONS這4類方法會被放行,其它Method的http請求,都要驗證_csrf的token是否正確,而一般post方式調用rest服務時,又沒有_csrf的token,因此校驗失敗。具體方法是重寫一個Matcher,當請求爲POST請求時添加一個排除校驗的url列表。html
解決辦法:前端
一、在jsp頁面的head標籤內添加以下代碼:
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>ajax
二、在ajax請求前添加以下代碼:
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);
});spring
等同下面:json
var header = $("meta[name='_csrf_header']").attr("content"); app
var token = $("meta[name='_csrf']").attr("content"); jsp
$.ajax({ async
url: '/test', post
type: 'POST', ui
beforeSend: function(xhr){
xhr.setRequestHeader(header, token);
},
success: function(data) {
console.log(data);
},
error:function(xhr,ajaxOptions, thrownError) { console.log(xhr.status + ": " + thrownError);
} });
<sec:csrfMetaTags/>
等同於:
<head><meta name="_csrf" content="${_csrf.token}"/><meta name="_csrf_header" content="${_csrf.headerName}"/></head>
1.前端無form表單,在頭部增長兩個meta標籤
<html> <head> <meta name="_csrf" th:content="${_csrf.token}" content=""/> <!-- default header name is X-CSRF-TOKEN --> <meta name="_csrf_header" th:content="${_csrf.headerName}" content=""/> <!-- ... --> </head>
2.前端有form表單
Spring Security爲Thymeleaf中的表單中自動添加一個<input type="hidden" name = "_csrf" value="xxxxxxxxxx"> (xxxx爲crrf.token)
var token = $("meta[name='_csrf']").attr("content"); var header = $("meta[name='_csrf_header']").attr("content");
$.ajax({ type: "POST", url: "myposturl", data: entID, contentType:"application/json; charset=utf-8", headers : {header:token}, async:false, success:function(data){ //do something }, error: function () { //deal width error } });
這裏header裏面的值爲"X-CSRF-TOKEN"
第二部分:驗證碼部分,在登錄過程當中可能會加入驗證碼驗證,此時須要作出一些改變。
第一種:自定義一個過濾器,工做在spring security的過濾器前面實現驗證碼的較驗。
第二種:寫一個filter,繼承UsernamePasswordAuthenticationFilter,重寫attemptAuthentication方法實現驗證碼的校驗,若校驗不成功拋出異常。
第三種:替換UsernamePasswordAuthenticationFilter這個filter來自定義校驗。