Vue3+Spring Boot3实现跨域通信解决办法

发布于:2024-04-19 ⋅ 阅读:(34) ⋅ 点赞:(0)

1 跨域是什么?

在这里插入图片描述

跨域资源共享(Cross-Origin Resource Sharing,CORS)是一种浏览器的安全策略,用于限制网页中的Javascript代码对不同源(Origin)的资源的访问。同源策略(Same-Origin Policy)是浏览器的一种安全特性,在发生异步请求的时候,它限制了来自不同源的页面之间的交互,以防止恶意代码窃取用户数据或执行恶意操作。

更多请看:使用Postman发送跨域请求实验

2 何为同源呢?

同源指的是协议相同、域名相同和端口相同。当网页尝试从一个源的域、协议、端口中的任何一个与当前页面不同的资源进行请求时,就会触发跨域问题。

  • 协议相同、域名相同和端口相同
  • 必须满足三者都相同

3 解决办法

3.1 全局配置

3.1.1 实现CorsFilter过滤器

创建CorsFilter过滤器类,实现过滤器方法,这个过滤器实现跨域的原理是利用了通过设置响应头来允许跨域请求。

package com.song.filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @author song
 * @version 0.0.1
 * @date 2024/4/10 18:55
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        httpServletResponse.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
        httpServletResponse.setHeader("Access-Control-Max-Age", "3600");

        if ("OPTIONS".equalsIgnoreCase(httpServletRequest.getMethod())) {
            httpServletResponse.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

3.1.2 实现SpringMVC配置类

这个通过实现WebMvcConfigurer 接口,重写addCorsMappings方法,手动添加CORS配置项。使用ctrl + o可以调出可重写方法。

package com.song.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author song
 * @version 0.0.1
 * @date 2024/4/10 19:03
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("127.0.0.1:8081")
                .allowedMethods("*");
    }
}

3.1.3 创建CorsFilterFactory工厂类返回CorsFilter对象

和上面过滤器原理差不多。上面是直接继承了Filter类。这里是使用的构造方法。

package com.song.filter;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @author song
 * @version 0.0.1
 * @date 2024/4/10 19:49
 */

@Component
public class CorsFilterFactory {

    @Bean
    public CorsFilter getCorsFilter(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //放行哪些原始请求头部信息
        corsConfiguration.addAllowedHeader("*");
        //放行哪些请求方式
        corsConfiguration.addAllowedMethod("*");
        //放行哪些原始域
        corsConfiguration.addAllowedOrigin("*");
        //是否发送 Cookie        corsConfiguration.setAllowCredentials(true);
        //暴露哪些头部信息
        corsConfiguration.addExposedHeader("*");

        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);

        return new CorsFilter(corsConfigurationSource);
    }

}

3.2 局部跨域

3.2.1 注解配置

在类或方法上添加如下注解,可以实现指定类下面的所有方法或单独方法实现跨域。

@CrossOrigin("*") //允许所有源
@CrossOrigin("http://localhost:5173/") //指定http://localhost:5173/
//指定多个origin,以及指定method
@CrossOrigin(value = {"http://localhost:5173/", "http://127.0.0.1:5173/"}, methods = {RequestMethod.GET})
@CrossOrigin("*")
@RequestMapping("/user")
public Map<String, String> testCORS(@RequestHeader HttpHeaders httpHeaders) {
    System.out.println("Origin:" + httpHeaders.getOrigin());
    HashMap<String, String> map = new HashMap<>();
    map.put("Origin", httpHeaders.getOrigin());
    return map;
}

3.2.2 手动设置响应头(局部跨域)

使用 HttpServletResponse 对象添加响应头(Access-Control-Allow-Origin)来授权原始域,这里 Origin的值也可以设置为 “*”,表示全部放行。

@RequestMapping("/user/getCaptcha")  
public ResponseEntity<byte[]> getCaptcha(HttpServletResponse response) throws IOException {  
    response.addHeader("Access-Allow-Control-Origin","*"); 
     
    byte[] captcha = CaptchaUtil.getCaptcha(100, 30, 4);  
  
    // 设置响应头  
    HttpHeaders httpHeaders = new HttpHeaders();  
    httpHeaders.setContentType(MediaType.IMAGE_JPEG);  
    httpHeaders.setContentLength(captcha.length);  
  
    return new ResponseEntity<>(captcha, httpHeaders, HttpStatus.OK);  
}