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