0


6.1 SpringBoot解决跨域,我推荐这2种超实用方案

文章目录


前言

在文章【2-2】中,我和你介绍了支持跨域的最简单方法,即在Controller上增加@CrossOrigin注解。通过这个方法,我们临时支持了跨域,但是这种方法对跨域的支持并不彻底,当前端发送options预检请求时,依然会出现跨域CORS error。
今天这篇文章分享了我使用SpringBoot解决跨域问题的经验和方法,并提供了详细的代码示例和解释,适合对跨域问题不太熟悉的读者。
主要讲解SpringBoot如何解决跨域,首先会验证跨域,然后再给出我推荐的2种超实用解决跨域方案!


一、验证跨域

模拟前端地址:

http://localhost:8080/index.html

后端接口地址:

http://localhost:8081/auth/test/cors

思路:启动两个springboot项目:8080端口和8081端口,在8080端口的静态资源目录index.html中,对8081端口的接口发起请求,因为端口不同,所以属于跨域,从而就可以验证不同请求(

POST或OPTIONS等方法

)是否报CORS error !

1. 添加index.html

在 tg-book-web的resources下,新建static\index.html

逻辑:使用ajax发送请求,调用8081的/auth/test/cors接口,如果执行成功,将结果输出到id="result"的div下,如下代码是

post

请求,后面还会改成

options

请求测试.

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><scripttype="text/javascript"src="https://code.jquery.com/jquery-3.1.1.min.js"></script></head><body><divid="result"></div></body><scripttype="text/javascript">
    $.ajax({
        url:'http://localhost:8081/auth/test/cors',
        method:'post',success:function(res){
            console.log(res)$('#result').append('<p>'+ res['message']+'</p>')}})</script></html>

对index.html不进行接口身份认证
因为我们增加了身份认证AuthInterceptor,所以需要在AuthInterceptor的preHandle过滤掉index.html,如下:

@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException{System.out.println("AuthInterceptor.preHandle:"+ request.getServletPath());if(request.getServletPath().startsWith("/index.html")){returntrue;}...其它代码
}

2. 增加/auth/test/cors接口

AuthController下增加接口

@PostMapping("/test/cors")publicTgResult<String>testCors(){returnTgResult.ok();}

同样,将/auth/test/cors也不进行接口身份认证.
排除身份认证是为了更好的测试跨域,所以同样写在排除"/auth/login"的位置.

registry.addInterceptor(authInterceptor).addPathPatterns("/**")// 排除的请求路径.excludePathPatterns("/auth/login","/auth/test/cors");

3. IDEA启动多个springboot项目

关于如何使用IDEA启动多个springboot项目,我就不演示了,我启动了8080和8081两个端口:

在这里插入图片描述

4. 验证POST方法

在浏览器打开 http://localhost:8080/index.html,如下图:

在这里插入图片描述

可以看到,8080/index.html通过ajax请求了8081的接口,返回200,说明支持POST请求跨域!

5. 验证OPTIONS方法

OK,正如我开头所说,

@CrossOrigin注解对options方法并没有支持跨域

,我们来试一试!

只需将index.html中的 【 method: ‘post’】改为【 method: ‘options’】,重启8080服务,然后用同样的方法测试,如下,报CORS error了 🤣

在这里插入图片描述

详细报错:
在这里插入图片描述


二、拦截器方案

关于拦截器,我在3-3. SpringBoot项目集成【用户身份认证】实战 【全流程篇】基于JWT+双重检查的登录+登出+拦截器 有详细的介绍,SpringBoot中使用拦截器需要2步:

  • 定义拦截器
  • 注册拦截器,并指定拦截规则

定义拦截器

新增一个拦截器类

CorsInterceptor

实现 HandlerInterceptor 接口

package org.tg.book.web.interceptor;

@ComponentpublicclassCorsInterceptorimplementsHandlerInterceptor{@OverridepublicbooleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler){// 允许跨域源,全部允许为*,否则写允许请求的源ipif(StringUtils.isEmpty(request.getHeader("Origin"))){
            response.setHeader("Access-Control-Allow-Origin","*");}else{
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));}
        response.setHeader("Access-Control-Allow-Credentials","true");// 允许跨域方法:全部允许为*,否则写具体的方法,例如:GET, POST, PUT, DELETE, OPTIONS
        response.setHeader("Access-Control-Allow-Methods","*");
        response.setHeader("Access-Control-Max-Age","86400");// 允许跨域请求头
        response.setHeader("Access-Control-Allow-Headers","*");// 如果是OPTIONS,不走后续操作,直接返回if(HttpMethod.OPTIONS.toString().equals(request.getMethod())){
            response.setStatus(HttpServletResponse.SC_OK);returnfalse;}returntrue;}}
  • Access-Control-Allow-Origin: 允许跨域源,全部允许为*,否则写允许请求的源ip。重点:通常会使用白名单机制,只有request.getHeader(“Origin”) 在白名单中才允许跨域。
  • Access-Control-Allow-Methods:允许跨域方法:全部允许为*,否则写具体的方法,例如:GET, POST, PUT, DELETE, OPTIONS

注册拦截器,并指定拦截规则

在原有的

InterceptorConfig

中增加注入CorsInterceptor ,并将【跨域拦截器】 放在 【身份认证拦截器】之前,如下:

@ConfigurationpublicclassInterceptorConfigimplementsWebMvcConfigurer{@AutowiredprivateCorsInterceptor corsInterceptor;@AutowiredprivateAuthInterceptor authInterceptor;@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){// 新增的跨域拦截器
        registry.addInterceptor(corsInterceptor).addPathPatterns("/**");// 身份认证拦截器
        registry.addInterceptor(authInterceptor).addPathPatterns("/**")// 排除的请求路径.excludePathPatterns("/auth/login");}}
去除原来的 @CrossOrigin注解

,然后验证,同样,完全支持POST和OPTIONS方法!

在这里插入图片描述


三、过滤器方案

新增

CorsFilter

实现

Filter

接口

publicclassCorsFilterimplementsFilter{@Overridepublicvoidinit(FilterConfig filterConfig)throwsServletException{}@OverridepublicvoiddoFilter(ServletRequest req,ServletResponse res,FilterChain chain)throwsIOException,ServletException{HttpServletResponse response =(HttpServletResponse) res;HttpServletRequest request =(HttpServletRequest) req;if(StringUtils.isEmpty(request.getHeader("Origin"))){
            response.setHeader("Access-Control-Allow-Origin","*");}else{
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));}
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Allow-Methods","*");
        response.setHeader("Access-Control-Max-Age","86400");
        response.setHeader("Access-Control-Allow-Headers","*");// 如果是OPTIONS,不走后续操作,直接返回if(HttpMethod.OPTIONS.toString().equals(request.getMethod())){
            response.setStatus(HttpServletResponse.SC_OK);return;}
        chain.doFilter(request, response);}@Overridepublicvoiddestroy(){}}

新增配置类

CorsConfig

注入

CorsFilter
@ConfigurationpublicclassCorsConfig{@BeanpublicCorsFiltercorsFilter(){returnnewCorsFilter();}}
注意:测试时先注释上面的 跨域拦截器

,然后验证,完全支持POST和OPTIONS方法!


总结

今天我使用了两种方案解决跨域:拦截器和过滤器方案,都是超实用的方案。另外,给你留个作业吧,都做成配置扩展,而不是hard code,例如上面说到的白名单机制,实际就是配置一堆ip,其它也是同理,你可以把你的配置扩展写在留言区里,或者遇到的问题在留言区和我一起讨论,感谢你的阅读,也欢迎你把这篇文章分享给更多的朋友一起阅读。

最后

给大家推荐一门专栏课程–>《基于SpringBoot+SpringCloud+Vue前后端分离项目实战》,由我和 前端狗哥 合力打造的一款专栏,可以让你从0到1快速拥有企业级规范的项目实战经验!

具体的优势、规划、技术选型都可以在《开篇》试读!

博主保证会用心持续高质量输出文章哦!

订阅专栏后也可以添加博主的微信,博主会为每一位用户进行针对性指导!

另外,别忘了关注我:天罡gg ,发布新文不容易错过: https://blog.csdn.net/scm_2008

老规矩,请投票给我反馈,谢谢大家的支持!

标签: spring boot java 跨域

本文转载自: https://blog.csdn.net/scm_2008/article/details/130736293
版权归原作者 天罡gg 所有, 如有侵权,请联系我们删除。

“6.1 SpringBoot解决跨域,我推荐这2种超实用方案”的评论:

还没有评论