SpringBoot业务开发 06、SpringBoot跨域问题解决方案

简介: SpringBoot业务开发 06、SpringBoot跨域问题解决方案

起因


当我们前后端分离时,前端发送请求就非常有可能出现跨域问题。




此时浏览器在本地的5500端口运行,此时若是发送给本地的9999就会出现跨域问题!



描述:浏览器中有同源策略,其指的是发送请求的协议、域名以及端口必须与向后端的请求一致,否则就会跨域问题。想要解决跨域问题,就需要后端添加响应头Access-Control-Allow-Origin属性。



Springboot解决方案


1、添加@CrossOrigin


注解源码


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
  @Deprecated
  String[] DEFAULT_ORIGINS = {"*"};
  @Deprecated
  String[] DEFAULT_ALLOWED_HEADERS = {"*"};
  @Deprecated
  boolean DEFAULT_ALLOW_CREDENTIALS = false;
  @Deprecated
  long DEFAULT_MAX_AGE = 1800;
  String[] value() default {};
  @AliasFor("value")
  String[] origins() default {};
  String[] originPatterns() default {};
  String[] allowedHeaders() default {};
  String[] exposedHeaders() default {};
  RequestMethod[] methods() default {};
  String allowCredentials() default "";
  long maxAge() default -1;
}



String[] origins: 允许来源域名的列表,例如 'www.jd.com',匹配的域名是跨域预请求 Response 头中的 'Access-Control-Aloow_origin' 字段值。不设置确切值时默认支持所有域名跨域访问。
String[] allowedHeaders: 跨域请求中允许的请求头中的字段类型, 该值对应跨域预请求 Response 头中的 'Access-Control-Allow-Headers' 字段值。 不设置确切值默认支持所有的header字段(Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma)跨域访问。
String[] exposedHeaders: 跨域请求请求头中允许携带的除Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma这六个基本字段之外的其他字段信息,对应的是跨域请求 Response 头中的 'Access-control-Expose-Headers'字段值。
RequestMethod[] methods: 跨域HTTP请求中支持的HTTP请求类型(GET、POST...),不指定确切值时默认与 Controller 方法中的 methods 字段保持一致。
String allowCredentials: 该值对应的是是跨域请求 Response 头中的 'Access-Control-Allow-Credentials' 字段值。浏览器是否将本域名下的 cookie 信息携带至跨域服务器中。默认携带至跨域服务器中,但要实现 cookie 共享还需要前端在 AJAX 请求中打开 withCredentials 属性。
long maxAge: 该值对应的是是跨域请求 Response 头中的 'Access-Control-Max-Age' 字段值,表示预检请求响应的缓存持续的最大时间,目的是减少浏览器预检请求/响应交互的数量。默认值1800s。设置了该值后,浏览器将在设置值的时间段内对该跨域请求不再发起预请求。


使用方式:


//方式一:在类上(表明该类所有方法都能够支持跨域)
@CrossOrigin
class public class UserController {}
//方式二:细粒度在方法上(表明该方法支持跨域)
@RestController
class public class UserController {
    @RequestMapping("/user")
    @CrossOrigin
    public String query(){
        ...
    }
}



2、全局CORS配置(实现WebMvcConfigurer的addCorsMappings方法)


定义全局CORS配置,来对指定模块进行跨域支持,类似于筛选器,我们在这里可以进行重写方法来实现针对指定映射地址来进行设置跨域:


@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    /**
     * 解决跨域问题
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/user/**")  //指定的映射地址
                .allowedHeaders("*") //允许携带的请求头
                .allowedMethods("*") //允许的请求方法
                .allowedOrigins("*");  //添加跨域请求头 Access-Control-Allow-Origin,值如:"https://domain1.com"或"*"
    }
}


3、基于filter的跨域实现(筛选白名单来进行跨域请求)


好处:基于这种方式的话我们能够对指定的url进行筛选来达到允许进行跨域请求的方式!!!


/**
 * @author ChangLu
 * @date 2021/08/30 11:29
 **/
@Component
public class CorsFilter extends OncePerRequestFilter {
    private static List<String> whiteList = new ArrayList<>();//跨域白名单
    static {
        whiteList.add("http://127.0.0.1:5500");
//        whiteList.add("http://jshopx.jd.com");
//        whiteList.add("http://mall.yao.jd.com");
//        whiteList.add("http://yao-shop.jd.com");
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //请求的地址
        String originUrl = request.getHeader("origin");
        //查看是否在白名单内
        boolean allow = whiteList.contains(originUrl);
        if(allow){
            response.setHeader("Access-Control-Allow-Origin", originUrl);
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
            response.setHeader("Access-Control-Max-Age", "1800");//30分钟
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with, content-type");
            filterChain.doFilter(request, response);
        }else{
            //对于非白名单域名的请求,不予进行访问,不然还会进入到controller方法中执行对应的逻辑
            return;
        }
    }
}



OncePerRequestFilter实际上则是实现了Filter,本质就是一个Filter过滤器,只不过这个也如同其名字一样在每次请求时只执行一次过滤,同样放行操作是执行的filterChain.doFilter()方法。



4、基于Nginx


在Nginx中添加以下的配置来解决跨域


location / {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers X-Requested-With;
    add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
    if ($request_method = 'OPTIONS') {
        return 204;
    }
}


相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
相关文章
|
2月前
|
Java
springboot+cors跨域处理
springboot+cors跨域处理
23 0
|
3月前
|
前端开发 Java 应用服务中间件
解决跨域问题的8种方法,含网关、Nginx和SpringBoot~
解决跨域问题的8种方法,含网关、Nginx和SpringBoot~
168 0
解决跨域问题的8种方法,含网关、Nginx和SpringBoot~
|
3月前
|
Java Spring
springboot跨域配置
springboot跨域配置
33 0
|
14天前
|
Java
Springboot文件下载跨域问题解决方案
Springboot文件下载跨域问题解决方案
|
5天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
44 10
|
5天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
14天前
|
Java
SpringBoot 配置解决跨域问题
SpringBoot 配置解决跨域问题
|
27天前
|
前端开发 Java 微服务
SpringBoot 企业级简化开发(一)
SpringBoot 企业级简化开发
104 1
|
1月前
|
安全 前端开发 JavaScript
spring boot3解决跨域的几种方式
spring boot3解决跨域的几种方式
59 3
|
2月前
|
Java API Maven
Springboot快速搭建跨域API接口(idea社区版2023.1.4+apache-maven-3.9.3-bin)
Springboot快速搭建跨域API接口(idea社区版2023.1.4+apache-maven-3.9.3-bin)
38 0