springboot+spring security無法實現跨域
未使用security時跨域:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.beans.factory.annotation.value; import org.springframework.boot.autoconfigure.autoconfigurebefore; import org.springframework.context.annotation.configuration; import org.springframework.format.formatterregistry; import org.springframework.web.servlet.config.annotation.*; @configuration @autoconfigurebefore (securityconfig. class ) public class mymvcconfigurer implements webmvcconfigurer { public void addcorsmappings(corsregistry registry){ logger.info( "跨域已設置" ); registry.addmapping( "/**" ) .allowedorigins( "*" ) .allowedmethods( "*" ) .allowedheaders( "*" ) .allowcredentials( true ) .maxage( 3600 ); } } |
整合security時發現只用上述方法前后端分離時仍存在跨域問題,
解決方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
@configuration @autoconfigurebefore (swagger2configuration. class ) @enablewebsecurity @enableglobalmethodsecurity (prepostenabled = true ) @order (- 1 ) public class securityconfig extends websecurityconfigureradapter { @override protected void configure(httpsecurity http) throws exception { http.formlogin() .loginprocessingurl( "/user/login" ) .loginpage( "/singin.html" ) .successhandler(moyuauthenticationsuccesshandler) .failurehandler(moyuauthenticationfailurehandler) .and() .apply(moyusocialsecurityconfig) .and() .rememberme() .tokenrepository(persistenttokenrepository()) .tokenvalidityseconds( 3600 * 24 * 7 ) .userdetailsservice(userdetailsservice) .and() .authorizerequests() .antmatchers( "/user/login" , "/login" , "/singin.html" , "**" , "/**" ).permitall() .anyrequest() .authenticated() .and() .cors() .and() .csrf().disable(); } } |
重點加入代碼:
1
2
3
4
|
.and() .cors() //新加入 .and() .csrf().disable(); |
引用spring security 項目的跨域處理
最近項目采用了前后端分離的框架,前端和后臺接口沒有部署到一個站點,出現了跨域問題,什么是跨域,這里就不再贅述,直接說解決辦法。
spring 解決跨域的方式有很多,個人采用了crosfilter的方式
具體代碼如下:
1
2
3
4
5
6
7
8
9
10
11
|
@bean public corsfilter corsfilter() { final urlbasedcorsconfigurationsource urlbasedcorsconfigurationsource = new urlbasedcorsconfigurationsource(); final corsconfiguration corsconfiguration = new corsconfiguration(); corsconfiguration.setallowcredentials( true ); corsconfiguration.addallowedorigin( "*" ); corsconfiguration.addallowedheader( "*" ); corsconfiguration.addallowedmethod( "*" ); urlbasedcorsconfigurationsource.registercorsconfiguration( "/**" , corsconfiguration); return new corsfilter(urlbasedcorsconfigurationsource); } |
配置完成后,測試調用,報錯401,依然不行。網上查資料得知,跨域請求會進行兩次。具體流程見下圖:
每次跨域請求,真正請求到達后端之前,瀏覽器都會先發起一個preflight request,請求方式為options 詢問服務端是否接受該跨域請求,具體參數如下圖:
但是該請求不能攜帶cookie和自己定義的header。
由于項目中引入了spring security ,而我使用的token傳遞方式是在header中使用authorization 字段,這樣依賴spring security攔截到 preflight request 發現它沒有攜帶token,就會報錯401,沒有授權。
解決這個問題很簡單,可以使用以下配置
讓spring security 不校驗preflight request 。
1
2
3
4
5
6
|
@override public void configure(httpsecurity http) throws exception { expressionurlauthorizationconfigurer<httpsecurity>.expressionintercepturlregistry registry = http.authorizerequests(); registry.requestmatchers(corsutils::ispreflightrequest).permitall(); //讓spring security放行所有preflight request } |
再試就搞定了,但是后端直接配置支持跨域會導致兩次請求。還使用另一種方式,使用nginx 轉發一下請求也可以。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/w903328615/article/details/80503750