SpringBoot:如何解决跨域问题?
⽬录
跨域问题现象
been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
上⾯的意思就是 你访问⼀个什么地址被CORS 协议阻⽌, 没有 在Hearder ⾥⾯发现 Access-Control-Allow-Origin 的参数的 资源
跨域问题分析
跨域问题的原因:浏览器出于安全考虑,限制访问本站点以为的资源。
⽐如你有⼀个 ⽹站 127.0.0.1:8080/ , 并且上⾯挂了⼀个页⾯ ,那么在这个页⾯中 ,你只访问 本站点的 资源不会受到限制,但是你如果访问其他站点,⽐如 127.0.0.1:8081 的资源就会受到限制。
备注:暂且把 协议,域名,端⼝都⼀样的叫做同⼀个站点。
但是 带有 src 属性的标签可以没有这个 限制,⽐如 img ,script 等等。
在说说历史,以前的程序前后端不分离, 页⾯ 和 请求接⼝,在同⼀个 域名同⼀个端⼝下⾯。 所有 浏览器认为来源这个 站点的页⾯ ,请求的是同⼀个站点的 接⼝,那么久会允许。
⽐如 127.0.0.1:8080/index.html ,请求 127.0.0.1:8080/a/b/c/userLit 接⼝,这样是可以的
在说说现在,前后点分离,页⾯ 和接⼝⼀般不是⼀个程序,这样就不允许,就会抛出这个异常。
什么是源和跨域
springboot框架的作用源(origin)就是协议、域名和端⼝号。
URL由协议、域名、端⼝和路径组成,如果两个URL的协议、域名和端⼝全部相同,则表⽰他们同源。否则,只要协议、域名、端⼝有任何⼀个不同,就是跨域。
URL是否跨域原因
www.baidu/more/index.html不跨域三要素相同
map.baidu/跨域域名不同
www.baidu/index.html跨域协议不同
www.baidu:81/index.html跨域端⼝号不同
什么是同源策略?
同源策略(Same origin policy)是⼀种约定,它是浏览器最核⼼也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的⼀种实现。
同源策略⼜分为以下两种:
1. DOM同源策略:禁⽌对不同源页⾯DOM 进⾏操作。这⾥主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
2. XMLHttpRequest同源策略:禁⽌使⽤XHR对象向不同源的服务器地址发起HTTP请求。
Spring Boot:跨域问题解决
1. 创建⼀个filter解决跨域
项⽬中前后端分离部署,所以需要解决跨域的问题。 我们使⽤cookie存放⽤户登录的信息,在spring进⾏权限控制,当权限不符合时,直接返回给⽤户固定的json结果。 当⽤户登录以后,正常使⽤;当⽤户退出登录状态时或者token过期时,由于和跨域的顺序有问题,出现了跨域的现象。 我们知道⼀个http请求,先⾛filter,到达servlet后才进⾏的处理,如果我们把cors放在filter⾥,就可以优先于权限执⾏。
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
2. 基于WebMvcConfigurerAdapter配置加⼊Cors的跨域
跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,⽆法发送其他类型的请求,在 RESTful 风格的应⽤中,就显得⾮常鸡肋,因此我们推荐在后端通过 (CORS,Cross-origin resource sharing) 来解决跨域问题。这种解决⽅案并⾮ Spring Boot 特有的,在传统的 SSM 框架中,就可以通过 CORS 来解决跨域问题,只不过之前我们是在 XML ⽂件中配置 CORS ,现在可以通过实现WebMvcConfigurer接⼝然后重写addCorsMappings⽅法解决跨域问题。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
}
3. controller配置CORS
controller⽅法的CORS配置,您可以向@RequestMapping注解处理程序⽅法添加⼀个@CrossOrigin注解,以便启⽤CORS(默认情况下,@CrossOrigin允许在@RequestMapping注解中指定的所有源和HTTP⽅法):
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
其中@CrossOrigin中的参数:
1. value属性可以设置多个URL。
2. origins属性也可以设置多个URL。
3. maxAge属性指定了准备响应前的缓存持续的最⼤时间。就是探测请求的有效期。
4. allowCredentials属性表⽰⽤户是否可以发送、处理 cookie。默认为false
5. allowedHeaders 属性表⽰允许的请求头部有哪些。
6. methods 属性表⽰允许请求的⽅法,默认get,post,head。
@CrossOrigin不起作⽤的原因
1、是springMVC的版本要在4.2或以上版本才⽀持@CrossOrigin
2、⾮@CrossOrigin没有解决跨域请求问题,⽽是不正确的请求导致⽆法得到预期的响应,导致浏览器端提⽰跨域问题。
3、在Controller注解上⽅添加@CrossOrigin注解后,仍然出现跨域问题,解决⽅案之⼀就是:
在@RequestMapping注解中没有指定Get、Post⽅式,具体指定后,问题解决。
类似代码如下:
@CrossOrigin
@RestController
public class person{
@RequestMapping(method = RequestMethod.GET)
public String add() {
// 若⼲代码
}
}
参考链接:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论