基于SpringBoot解决CORS跨域的问题(@CrossOrigin)
一、关于跨域介绍
在前后分离的架构下,跨域问题难免会遇见比如,站点 http://domain-a.com 的某 HTML 页面通过 的 src 请求 http://domain-b.com/image.jpg。
网络上的许多页面都会加载来自不同域的CSS样式表,图像和脚本等资源。
出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。
例如,XMLHttpRequest和Fetch API遵循同源策略。
这意味着使用这些API的Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非使用CORS头文件。
跨域的体现,在于它的域名不同或者端口不同,但要注意以下的形式为非跨域模式
http://www.example.com/index.html ==> http://www.example.com/login.html
二、Spring Boot跨域(@CrossOrigin)
当然这里虽然指SpringBoot但是SpringMVC也是一样的,要求在Spring4.2及以上的版本
1、@CrossOrigin使用场景要求
jdk1.8+
Spring4.2+
2、@CrossOrigin源码解析(翻译参考网络,文末列出参考地址)
@Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CrossOrigin { String[] DEFAULT_ORIGINS = { "*" }; String[] DEFAULT_ALLOWED_HEADERS = { "*" }; boolean DEFAULT_ALLOW_CREDENTIALS = true; long DEFAULT_MAX_AGE = 1800; /** * 同origins属性一样 */ @AliasFor("origins") String[] value() default {}; /** * 所有支持域的集合,例如"http://domain1.com"。 * <p>这些值都显示在请求头中的Access-Control-Allow-Origin * "*"代表所有域的请求都支持 * <p>如果没有定义,所有请求的域都支持 * @see #value */ @AliasFor("value") String[] origins() default {}; /** * 允许请求头重的header,默认都支持 */ String[] allowedHeaders() default {}; /** * 响应头中允许访问的header,默认为空 */ String[] exposedHeaders() default {}; /** * 请求支持的方法,例如"{RequestMethod.GET, RequestMethod.POST}"}。 * 默认支持RequestMapping中设置的方法 */ RequestMethod[] methods() default {}; /** * 是否允许cookie随请求发送,使用时必须指定具体的域 */ String allowCredentials() default ""; /** * 预请求的结果的有效期,默认30分钟 */ long maxAge() default -1; }
3、@CrossOrigin使用
Spring Boot下的请求处理控制器
package com.example.demo.controller; import com.example.demo.domain.User; import com.example.demo.service.IUserFind; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @Title: UserController * @ProjectName demo * @Description: 请求处理控制器 * @author 浅然 * @date 2018/7/2022:18 **/ @RestController //实现跨域注解 //origin="*"代表所有域名都可访问 //maxAge飞行前响应的缓存持续时间的最大年龄,简单来说就是Cookie的有效期 单位为秒 //若maxAge是负数,则代表为临时Cookie,不会被持久化,Cookie信息保存在浏览器内存中,浏览器关闭Cookie就消失 @CrossOrigin(origins = "*",maxAge = 3600) public class UserController { @Resource private IUserFind userFind; @GetMapping("finduser") public User finduser(@RequestParam(value="id") Integer id){ //此处省略相应代码 } }
后台返回的数据
前端跨域请求
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>demo</title> <script type="text/javascript" src="js/jquery-3.3.1.min.js" ></script> </head> <body> <input type="button" value="测试" onclick="ajaxloding()" /> <div id="usermessage"></div> <script> var getdata=0; function ajaxloding(){ $.ajax({ async:false, type:"get", url:"http://localhost:8080/api/finduser?id=1", contentType: "application/x-www-form-urlencoded", dataType: "json", data: {}, success:function(result){ getdata=result.name }, error: function (errorMsg) { //请求失败时执行该函数 alert("请求数据失败!"); } }); $("#usermessage").text(getdata) } </script> </body> </html>
这样就解决了跨域问题,获取了后台的数据
参考
跨域 HTTP 请求
补充:springboot的@CrossOrigin("*")跨域仍然失效
项目中偶尔遇到即使加了@CrossOrigin跨域失败:
第一次遇到时间有限没解决:前端直接添加跨域处理。
jQuery.support.cors = true;
后续第二次遇到该问题,作为后端不能让前端解决跨域问题。
debug详细查找原因:发现在自定义拦截器返回失败,跨域失败。
明白该问题:需要以下知识。
(mvc拦截器的链路模式)
(Cors拦截器加载)
(自定义的拦截器加载)
(拦截器的加载顺序)
因为拦截器是链路模式:CrossOrigin也是拦截器在自定义拦截器之后。所以在自定义拦截器失败后,处理
跨域的拦截器未处理,造成跨域失败。
解决该问题的办法:
添加filter ,因为Filter优先于拦截器执行,所以自己创建的拦截器不会影响跨域处理。
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.setAllowCredentials(true); config.addAllowedMethod("*"); config.addAllowedHeader("*"); UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); return new CorsFilter(configSource); } }
二:springboot升级到2.2.0,在新版本的springmvc中,把cors拦截添加到了拦截器的第一位,所以不会有该问题。
如果允许可以直接升级springboot或mvc版本。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持猪先飞。如有错误或未考虑完全的地方,望不吝赐教。
相关文章
解决springboot使用logback日志出现LOG_PATH_IS_UNDEFINED文件夹的问题
这篇文章主要介绍了解决springboot使用logback日志出现LOG_PATH_IS_UNDEFINED文件夹的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-28- 这篇文章主要为大家详细介绍了SpringBoot实现excel文件生成和下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-09
- 这篇文章主要介绍了详解springBoot启动时找不到或无法加载主类解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-09-16
- 这篇文章主要介绍了SpringBoot集成Redis实现消息队列的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-10
- 这篇文章主要介绍了解决Springboot get请求是参数过长的情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-17
Spring Boot项目@RestController使用重定向redirect方式
这篇文章主要介绍了Spring Boot项目@RestController使用重定向redirect方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-02- 什么是js跨域呐?js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。要...2015-10-30
- 这篇文章主要介绍了Springboot+TCP监听服务器搭建过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-28
- 这篇文章主要介绍了springBoot 项目排除数据库启动方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-10
- 什么是js跨域呐?js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。要...2015-10-30
详解SpringBoot之访问静态资源(webapp...)
这篇文章主要介绍了详解SpringBoot之访问静态资源(webapp...),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-09-14- 这篇文章主要介绍了SpringBoot接口接收json参数解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-19
springboot中使用@Transactional注解事物不生效的坑
这篇文章主要介绍了springboot中使用@Transactional注解事物不生效的原因,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-01-26- 这篇文章主要介绍了springboot多模块包扫描问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-09-16
- 这篇文章主要介绍了jQuery Jsonp跨域模拟搜索引擎的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2017-06-24
Springboot mybatis plus druid多数据源解决方案 dynamic-datasource的使用详解
这篇文章主要介绍了Springboot mybatis plus druid多数据源解决方案 dynamic-datasource的使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-11-18- 这篇文章主要介绍了Springboot实现多线程注入bean的工具类操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-27
Springboot+MDC+traceId日志中打印唯一traceId
本文主要介绍了Springboot+MDC+traceId日志中打印唯一traceId,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-10-17- 这篇文章主要为大家详细介绍了原生JS封装Ajax插件,为大家介绍不同域之间互相请求资源的跨域...2016-05-05
SpringBoot部署到Linux读取resources下的文件及遇到的坑
本文主要给大家介绍SpringBoot部署到Linux读取resources下的文件,在平时业务开发过程中,很多朋友在获取到文件内容乱码或者文件读取不到的问题,今天给大家分享小编遇到的坑及处理方案,感兴趣的朋友跟随小编一起看看吧...2021-06-21