好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringBoot+Spring Security无法实现跨域的解决方案

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

查看更多关于SpringBoot+Spring Security无法实现跨域的解决方案的详细内容...

  阅读:18次