Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
SpringMVC教程
-> 跨域问题详解
1、Helloword
2、@Controller、@RequestMapping
3、接口测试利器
4、如何接受请求中的参数?
5、@RequestBody接收Json格式数据
6、多文件上传
7、返回页面常见的5种方式
8、返回json格式数据 & 通用返回值设计
9、SpringMVC返回null是什么意思?
10、异步处理请求
11、如何集成静态资源?
12、拦截器怎么用?
13、统一异常处理
14、实战篇:通用返回值 & 异常处理设计
15、全注解的方式 & 原理解析
16、源码解析SpringMVC处理请求的流程
17、源码解析SpringMVC容器的启动过程
18、RequestBodyAdvice:对@ReuqestBody进行增强
19、ResponseBodyAdvice:对@ResponseBody进行增强
20、RESTful接口详解
21、接口调用利器RestTemplate
22、参数解析器HandlerMethodArgumentResolver解密
23、@RequestParam用法及原理详解
24、@RequestBody原理解密
25、@RequestHeader详解
26、@CookieValue详解
27、@RequestAttribute详解
28、@SessionAttribute详解
29、重定向和转向详解
30、Converter转换器详解
31、跨域问题详解
32、类容协商,颠覆你的认知
33、终章
34、CORS通信
35、浏览器安全策略 & CORS
36、Http中的Content-Type详解
上一篇:Converter转换器详解
下一篇:类容协商,颠覆你的认知
<div style="display:none"></div> **大家好,我是路人,这是SpringMVC系列第31篇。** 今天又给大家带来了一个很重要的知识点:SpringMVC中如何处理跨域问题,本文的内容同样适合于SpringBoot ## 1、跨域访问报错 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。 出于安全原因,浏览器禁止Ajax调用驻留在当前原点之外的资源,比如从a.com发送一个ajax请求到b.com,则浏览器控制台会报跨域访问错误。 如下图,从`http://localhost:63342/`站点页面中向`ttp://localhost:8080/chat21/cors/test2`发送一个ajax请求,则出现了红色的错误信息,错误中包含了`Access-Controll-Allow-Origin`这样字样的错误,以后看到这个的时候,大家就要一眼看出来这是跨域问题。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/529cb6bb-5eeb-4b07-bfe6-26b4c7aac6b4.png) ## 2、同源定义 同源策略是浏览器的一个重要的安全策略,它用于限制一个源的文档或其加载的脚本如何与另外一个源进行交互,它能够隔绝恶意文档,减少被攻击的媒介。 如果两个URL的**协议**、**主机名**和**端口号**都是相同的,那么这两个URL就是同源的,否则不同源,不同源的访问就会出现跨域问题,就会出现上面的错误。 下表给出了与 URL `http://store.company.com/dir/page.html` 的源进行对比的示例: | URL | 结果 | 原因 | | ---------------------------------------- | ------ | ------------ | | http://store.company.com/dir2/other.html | 同源 | 只有路径不同 | | https://store.company.com/secure.html | 非同源 | 协议不同 | | http://store.company.com:81/dir/etc.html | 非同源 | 端口号不同 | | http://news.company.com/dir/other.html | 非同源 | 主机名不同 | 也就是说当在`http://store.company.com/dir/page.html`这个网站中向`https://store.company.com`、`http://store.company.com:81`和`http://news.company.com`三个地址发起`AXJX`请求都会失败并且会报跨域的错误。这就是浏览器的同源策略,只能访问同源的数据。 ## 3、跨域问题如何解决? 跨域问题需要使用CORS来解决,请求端和后端接口需要遵循CORS规则来通信,便可解决跨域访问的问题。 CORS全称Cross-Origin Resource Sharing, 即跨域资源共享,是一个由一系列HTTP头组成的系统,这些HTTP头决定浏览器是否阻止前端`javascript`代码获取跨域请求的响应。为什么需要CORS ? 这是因为浏览器存在同源安全策略,当我们在当前域请求另外一个域的资源时,浏览器默认会阻止脚本读取它的响应,这时CORS就有了用武之地。 跨源资源共享(CORS)是由大多数浏览器实现的W3C规范,允许您灵活地指定什么样的跨域请求被授权,而不是使用一些不太安全和不太强大的策略,如IFRAME或JSONP等。 ### 4、CORS原理 CORS的原理:简单点说,就是在请求头或响应头中添加了一些配置,通过这些配置来便可轻松解决跨域问题。 想详细了解CORS原理的,建议先阅读下面2篇文章,然后再继续向下看,否则,最后你知道SpringMVC是如何解决的,但是不知道本质的原理是什么。 - CORS通信:http://itsoku.com/article/197 - 浏览器安全策略 & CORS:http://itsoku.com/article/198 ## 5、SpringMVC中如何解决跨域问题? SpringMVC内部提供了跨域问题的解决方案,只需要做一些简单的配置,而接口基本上不用做任何修改,便可解决跨域问题。 SpringMVC解决跨域问题的原理也就是SpringMVC遵循了CORS通信的规则来解决了跨域的问题,在响应头中添加了一些CORS需要的信息。 SpringMVC中提供了3种方案来解决跨域问题,下面一起来了解下。 ## 6、方案1:方法或者类上标注@CrossOrigin注解 - 接口方法上标注`org.springframework.web.bind.annotation.CrossOrigin`注解,如下test1接口上标注了`@CrossOrigin`注解,这个接口就支持跨域访问,@CrossOrigin注解中含有更详细的配置,这里就不细说了 - 也可以在类上标注`@CrossOrigin`注解,那么这个类中所有接口会支持跨域访问 - 也可同时在类和方法上标注`@CrossOrigin`注解,最后方法上的跨域访问会取合并后的配置 ```java @RestController public class CorsController { @RequestMapping("/cors/test1") @CrossOrigin public List<String> test1() { List<String> result = Arrays.asList("www.itsoku.com", "Spring高手系列", "SpringMVC系列", "MySQL系列", "高并发系列"); return result; } } ``` ## 7、方案2:全局配置的方式 除了细粒度、基于注释的配置之外,您还可能需要定义一些全局CORS配置,这类似于使用筛选器,但可以声明为Spring MVC并结合细粒度@CrossOrigin配置。默认情况下,所有origins and GET, HEAD and POST methods是允许的。 ```java @EnableWebMvc @Configuration public class MvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { //每次调用registry.addMappin可以添加一个跨域配置,需要多个配置可以多次调用registry.addMapping registry.addMapping("/**") .allowedOrigins("*") //放行哪些原始域 .allowedMethods("PUT", "DELETE","POST", "GET") //放行哪些请求方式 .allowedHeaders("header1", "header2", "header3") //放行哪些原始请求头部信息 .exposedHeaders("header1", "header2") //暴露哪些头部信息 .allowCredentials(false) //是否发送 Cookie .maxAge(3600); // Add more mappings... } } ``` ## 8、方案3:拦截器的方式CorsFilter ```java //处理跨域的Filter //1. 添加 CORS配置信息 CorsConfiguration config = new CorsConfiguration(); //放行哪些原始域 config.addAllowedOrigin("*"); //是否发送 Cookie config.setAllowCredentials(false); //放行哪些请求方式 config.addAllowedMethod("*"); //放行哪些原始请求头部信息 config.addAllowedHeader("*"); //暴露哪些头部信息 config.addExposedHeader("*"); //2. 添加映射路径 UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource(); corsConfigurationSource.registerCorsConfiguration("/**",config); ``` ## 9、案例代码 ### 9.1、案例完整代码 ```html git地址:https://gitee.com/javacode2018/springmvc-series ``` ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/4f67d648-8577-4b90-866c-76be9c1e9875.png) ### 9.2、接口代码:CorsController > CorsController中有2个接口,第一个接口上标注了@CrossOrigin注解,可以解决跨域访问的问题,而第二个方法没有标注。 ```java @RestController public class CorsController { @RequestMapping("/cors/test1") @CrossOrigin public List<String> test1() { List<String> result = Arrays.asList("www.itsoku.com", "Spring高手系列", "SpringMVC系列", "MySQL系列", "高并发系列"); return result; } @RequestMapping("/cors/test2") public List<String> test2() { List<String> result = Arrays.asList("www.itsoku.com", "Spring高手系列", "SpringMVC系列", "MySQL系列", "高并发系列"); return result; } } ``` ### 9.3、静态页面:cors.html > 静态页面cors.html中添加了2个按钮,点击2个按钮的时候,分别以ajax跨域的方式访问上面2个接口,第1个按钮访问第一个接口,第2个按钮访问第二个接口,然后在浏览器控制台查看效果。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>cors</title> <script type="text/javascript" src="jquery-3.6.0.min.js"></script> <script type="text/javascript"> $(function () { $("#cors-btn1").click(function () { $.ajax({ url: "http://localhost:8080/chat21/cors/test1", success: function (data) { console.log(JSON.stringify(data)); } }); }); $("#cors-btn2").click(function () { $.ajax({ url: "http://localhost:8080/chat21/cors/test2", success: function (data) { console.log(JSON.stringify(data)); } }); }); }) </script> </head> <body> <button id="cors-btn1">跨域测试test1</button> <button id="cors-btn2">跨域测试test2</button> </body> </html> ``` ### 9.4、将chat21-cores模块发布到tomcat ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/f9062540-fa43-438a-a458-23dc5e8149a4.png) ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/04aa7d7c-b2dc-4823-9321-c15cad83380f.png) ### 9.5、运行静态页面cors.html 在idea中选中`cors.html`,然后鼠标右键->Run,即可运行 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/cdb5dc62-a0cb-4c5c-98c1-9dda519c982f.png) 运行效果如下(最好以chrome浏览器运行),idea中支持直接运行静态页面,大家注意这里的端口是63342,而上面tomcat的端口是8080,然后浏览器中按F12打开浏览器控制台,选中Console选项卡,稍后在这里可以看到点击按钮验证跨域的效果。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/3b3b4280-f851-4e6f-9ef1-b3e002d3f3e8.png) ### 9.6、点击第1个按钮,测试跨域正常请求 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/f99ea534-e219-432e-9a6e-1d7fbace4604.png) 再看看下面这个图,正常的跨域请求,响应头多了几个头,主要是Access-Control开头的头是和CORS相关的,浏览器就是根据这些响应头来决定跨域访问是不是正常的,如果没有这些头,浏览器将拒绝读取响应体,然后就报错啦。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/78578445-b350-4b1f-8b3d-b86aceac510b.png) ### 9.7、点击第2个按钮,测试跨域异常请求 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/632deb03-e492-40d1-88f5-d87f6c2b3021.png) ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/242/89a1f38d-b17f-463c-b515-825c7994f3f9.png) ## 10、总结 掌握SpringMVC中解决跨域问题的3种方式 1. 注解的方式:@CrossOrigin 2. 全局配置的方式:WebMvcConfigurer接口的addCorsMappings方法中注册CORS配置 3. 拦截器的方式:CorsFilter <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
#custom-toc-container