先說說SpringSecurity如何實現前后端分離Ajax登錄?
今天使用SpringBoot整合SpringSecurity中想使用Ajax替代SpringSecurit的Form表單提交,在這里我們的提交方式還是使用表單提交
http.formLogin().loginProcessingUrl("/authentication/form")
loginProcessingUrl方法表示你登錄請求的地址,在這里SpringSecurity默認登錄頁面地址是/login ,填寫了username與password 上送的地址就是loginProcessingUrl方法指定的地址,
如果你想使用Ajax登錄+Token驗證,或者是移動端不得不這樣做的時候,那么你就不用管SpringSecurity的默認登錄地址啦,只需要注意 在Ajax請求的時候 登錄名必須是username字段
密碼必須是 password字段 登錄提交的地址就是loginProcessingUrl方法指定的路徑/authentication/form
因為在SpringSecurity中處理賬號密碼登錄的過濾器是UsernamePasswordAuthenticationFilter 而這個登錄處理類里面寫死了這兩個字段的名稱,如下圖源碼中所見:
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { // ~ Static fields/initializers // ===================================================================================== public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username"; public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
我測試的前端登錄代碼如下:
$.ajax({
url:"http://127.0.0.1/authentication/form",
timeout : 20000,
type:"post",
dataType:"json",
data:{
username:"088358",password:"123"
},
success:function(data){
alert('ok')
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("1 異步調用返回失敗,XMLHttpResponse.readyState:"+XMLHttpRequest.readyState);
alert("2 異步調用返回失敗,XMLHttpResponse.status:"+XMLHttpRequest.status);
alert("3 異步調用返回失敗,textStatus:"+textStatus);
alert("4 異步調用返回失敗,errorThrown:"+errorThrown);
}
})
后端在執行登錄成功之后處理代碼
后端在執行登錄成功之后會回調AuthenticationSuccessHandler攔截器的onAuthenticationSuccess方法,我們只需要寫一個類集成AuthenticationSuccessHandler就可以重寫這個方法來生成token返回給前端了,Token如何生成,請看上一章jwtToken的使用 https://www.cnblogs.com/langjunnan/p/12464791.html ,這章不細說
@Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 登錄成功之后 List<Object> functs = (List<Object>) authentication.getAuthorities();// 當前功能列表 String loginName = authentication.getName();// 登錄名 Users obj = (Users) authentication.getPrincipal();// 用戶信息 String token = JwtUtil.createToken(loginName, functs, obj);// 生成token response.setHeader(JwtUtil.TOKEN_HEADER, JwtUtil.TOKEN_PREFIX + token); response.setContentType("application/json;charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); PrintWriter pw = response.getWriter(); DTO dto = new DTO<>(); dto.setCode("000000"); dto.setMessage("認證通過"); String json=JsonUtil.set(dto); System.out.println(json); pw.println(json); // println 等於pw.flush()+pw.close(); } }
代碼是沒有問題的,但是由於跨域的問題Ajax是調用不成功的,
SpringSecurity中的跨域問題
之前寫項目都是自己定義一個過濾器來解決跨域問題,但是這次過濾器不好用了,只能把跨域資源配置到SpringSecurity中了
代碼如下
http.cors().configurationSource(CorsConfigurationSource())//允許跨域訪問
/*跨域原*/ private CorsConfigurationSource CorsConfigurationSource() { CorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); //同源配置,*表示任何請求都視為同源,若需指定ip和端口可以改為如“localhost:8080”,多個以“,”分隔; corsConfiguration.addAllowedHeader("*");//header,允許哪些header,本案中使用的是token,此處可將*替換為token; corsConfiguration.addAllowedMethod("*"); //允許的請求方法,PSOT、GET等 ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**",corsConfiguration); //配置允許跨域訪問的url return source; }