[In-depth explanation of Spring Security (9)] Solving cross-domain problems and Axios required configuration

What is cross domain?
In this blog of the editor, I expounded- 【AJAX】The cross-domain problem of AJAX , this article only talks about the cross-domain solution.

Here is a description of the core code of the front-end in the SpringMVC cross-domain solution test case below, just an Ajax request, and then render the content: first,
some axiosinitialization of :
insert image description herethen send an Ajax request to the backend, and render the response data, the code is as follows :

<script setup>
import {
     
      ref } from 'vue'
import axios from '../utils/index.js'
const content = ref('')

axios.get(`/test`).then(res=>{
     
     
    content.value = res
}).catch(err=>{
     
     
    console.log(err)
})
</script>

<template>
    <div>{
   
   {content}}</div>
</template>

If there is no cross-domain success, the following error will occur:
insert image description here

1. SpringMVC cross-domain solution

@CrossOrigin (solved by annotation)

The first way to deal with cross-domain in SpringMVC is to mark support for cross-domain through the @CrossOrigin annotation. This annotation can be added to the method or class - according to the meta-annotation framed below: the specific case configuration is as
insert image description herefollows :

@RestController
public class TestController {
    
    

    @CrossOrigin("http://localhost:5173")
    @GetMapping("/test")
    public String test(){
    
    
        return "test";
    }

}

@CrossOrigin annotation attributes have the following meanings:

  • maxAge: The validity period of the preflight request. During the validity period, there is no need to send the preflight request again. The default is -1.
  • methods: Allowed request methods, *which means that all methods (request methods) are allowed.
  • origins: Allowed domains, *which means that all domains are allowed, which is the same as the value attribute.

The case test results are as follows

insert image description here

addCorsMappings (implement the WebMvcConfigurer interface, override the method)

The @CrossOrigin annotation needs to be added to different Controllers. Therefore, there is another global configuration method, which is WebMvcConfigurer#addCorsMappingsrealized by rewriting the method. The specific configuration is as follows:

@Configuration
public class WebMvcOriginConfig implements WebMvcConfigurer {
    
    

    @Override
    public void addCorsMappings(CorsRegistry registry) {
    
    
        registry.addMapping("/**")// 对所有请求进行跨域
                .allowedOriginPatterns("http://localhost:5173")
                .maxAge(-1)
                .allowedMethods("*");
    }
}

TestController

@RestController
public class TestController {
    
    

    // @CrossOrigin("http://localhost:5173")
    @GetMapping("/test")
    public String test(){
    
    
        return "test";
    }

}

Test Results

insert image description here

2. Spring Security cross-domain solution

When we add Spring Security dependencies to the project, the above two cross-domain methods will fail.So we have to understand the cross-domain solution provided by Spring Security.

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    
    
        return http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .addFilterAfter(loginFilter(http),LogoutFilter.class)
                .cors()
                .configurationSource(this.corsConfigurationSource())
                .and()
                .csrf()
                .disable()
                .build();
    }

    private CorsConfigurationSource corsConfigurationSource(){
    
    
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.addAllowedHeader("*"); // 这个得加上,一些复杂的请求方式会带有header,不加上跨域会失效。
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addExposedHeader("*");
        corsConfiguration.addAllowedOriginPattern("http://localhost:5173");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }

Note 1:corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedHeader(" * “);
corsConfiguration.addExposedHeader(” * ");
All three should be added. Reason 1: Requests sent by some request methods will have request headers. If not allowed, they will be filtered CorsFilterout by the filter, that is, cross-domain failure; Reason 2: If the credential information is not included, then the authentication filter time will fail, causing the request to fail.

Note 2: In the method of configuring the security filter chain, there is a custom LoginFilter configured, which is used to process login authentication in JSON format. There is a special blog description in the Xiaobian's Spring Security column, which will not be explained in detail here up.

Front-end and back-end cross-domain testing (front-end related configuration)

Due to the integration of Spring Security, authentication is required after login. After authentication, the resource to be authenticated on the server side needs to carry its authentication cookie (that is, the SessionID, indicating that it has been authenticated). Then when using Axios to send cross-domain requests on the front end, configuration is required axios.defaults.withCredentials = true. This is used to control whether to carry identity credentials (such as cookies, Http authentication, etc.) when sending cross-domain requests . Of course, the backend also needs to be configured. (Of course, if you don’t integrate Spring Security, you don’t need to configure this, because the login authentication is done according to the procedure you set yourself, and it’s not managed by Spring Security for you.)

Front-end code:

Axios related configuration

insert image description here
test code

<script setup>
import {
     
      ref } from 'vue'
import axios from '../utils/index.js'
const content = ref('')

const userInfo = {
     
     
    "username" : "root",
    "password" : "123"
}
let flag = false
function login() {
     
     
    axios.post(`/api/auth/login`, userInfo).then(res => {
     
     
        console.log(res)
        content.value = JSON.stringify(res)
        flag = true
    }).catch(err=>{
     
     
        console.log(666999)
        console.log(err)
    })
}

function test(){
     
     
    axios.get(`/test`,{
     
     
        withCredentials: true,   //设置跨域的时候传递cookie,需要服务端的配合
    }).then(res=>{
     
     
        console.log(res)
        content.value = res
    }).catch(err=>{
     
     
        console.log(666)
        console.log(err)
    })
}

</script>

<template>
    <div>
        <button @click="login">登录</button><br><br>
        <button @click="test">发送测试请求</button><br><br>
        <div>
            <p>{
   
   {content}}</p>
        </div>
    </div>
</template>


Test Results

Please add a picture description

Guess you like

Origin blog.csdn.net/qq_63691275/article/details/131159686