今天和小伙伴们来聊一聊经过CORS解决跨域问题。javascript
不少人对跨域有一种误解,觉得这是前端的事,和后端不要紧,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略。html
同源策略是由 Netscape 提出的一个著名的安全策略,它是浏览器最核心也最基本的安全功能,如今全部支持 JavaScript 的浏览器都会使用这个策略。所谓同源是指协议、域名以及端口要相同。同源策略是基于安全方面的考虑提出来的,这个策略自己没问题,可是咱们在实际开发中,因为各类缘由又常常有跨域的需求,传统的跨域方案是 JSONP,JSONP 虽然能解决跨域可是有一个很大的局限性,那就是只支持 GET 请求,不支持其余类型的请求,而今天咱们说的 CORS(跨域源资源共享)(CORS,Cross-origin resource sharing)是一个 W3C 标准,它是一份浏览器技术的规范,提供了 Web 服务从不一样网域传来沙盒脚本的方法,以避开浏览器的同源策略,这是 JSONP 模式的现代版。前端
在 Spring 框架中,对于 CORS 也提供了相应的解决方案,今天咱们就来看看 SpringBoot 中如何实现 CORS。java
接下来咱们就来看看 Spring Boot 中如何实现这个东西。ajax
首先建立两个普通的 Spring Boot 项目,这个就不用我多说,第一个命名为 provider 提供服务,第二个命名为 consumer 消费服务,第一个配置端口为 8080,第二个配置配置为 8081,而后在 provider 上提供两个 hello 接口,一个 get,一个 post,以下:后端
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
@PostMapping("/hello")
public String hello2() {
return "post hello";
}
}
复制代码
在 consumer 的 resources/static 目录下建立一个 html 文件,发送一个简单的 ajax 请求,以下:跨域
<div id="app"></div>
<input type="button" onclick="btnClick()" value="get_button">
<input type="button" onclick="btnClick2()" value="post_button">
<script> function btnClick() { $.get('http://localhost:8080/hello', function (msg) { $("#app").html(msg); }); } function btnClick2() { $.post('http://localhost:8080/hello', function (msg) { $("#app").html(msg); }); } </script>
复制代码
而后分别启动两个项目,发送请求按钮,观察浏览器控制台以下:浏览器
Access to XMLHttpRequest at 'http://localhost:8080/hello' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
复制代码
能够看到,因为同源策略的限制,请求没法发送成功。安全
使用 CORS 能够在前端代码不作任何修改的状况下,实现跨域,那么接下来看看在 provider 中如何配置。首先能够经过 @CrossOrigin
注解配置某一个方法接受某一个域的请求,以下:bash
@RestController
public class HelloController {
@CrossOrigin(value = "http://localhost:8081")
@GetMapping("/hello")
public String hello() {
return "hello";
}
@CrossOrigin(value = "http://localhost:8081")
@PostMapping("/hello")
public String hello2() {
return "post hello";
}
}
复制代码
这个注解表示这两个接口接受来自 http://localhost:8081
地址的请求,配置完成后,重启 provider ,再次发送请求,浏览器控制台就不会报错了,consumer 也能拿到数据了。
此时观察浏览器请求网络控制台,能够看到响应头中多了以下信息:
这个表示服务端愿意接收来自 http://localhost:8081
的请求,拿到这个信息后,浏览器就不会再去限制本次请求的跨域了。
provider 上,每个方法上都去加注解未免太麻烦了,有的小伙伴想到能够讲注解直接加在 Controller 上,不过每一个 Controller 都要加仍是麻烦,在 Spring Boot 中,还能够经过全局配置一次性解决这个问题,全局配置只须要在 SpringMVC 的配置类中重写 addCorsMappings 方法便可,以下:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8081")
.allowedMethods("*")
.allowedHeaders("*");
}
}
复制代码
/**
表示本应用的全部方法都会去处理跨域请求,allowedMethods 表示容许经过的请求数,allowedHeaders 则表示容许的请求头。通过这样的配置以后,就没必要在每一个方法上单独配置跨域了。
了解了整个 CORS 的工做过程以后,咱们经过 Ajax 发送跨域请求,虽然用户体验提升了,可是也有潜在的威胁存在,常见的就是 CSRF(Cross-site request forgery)跨站请求伪造。跨站请求伪造也被称为 one-click attack 或者 session riding,一般缩写为 CSRF 或者 XSRF,是一种挟制用户在当前已登陆的 Web 应用程序上执行非本意的操做的攻击方法,举个例子:
假如一家银行用以运行转帐操做的URL地址以下:
http://icbc.com/aa?bb=cc
,那么,一个恶意攻击者能够在另外一个网站上放置以下代码:<img src="http://icbc.com/aa?bb=cc">
,若是用户访问了恶意站点,而她以前刚访问过银行不久,登陆信息还没有过时,那么她就会遭受损失。
基于此,浏览器在实际操做中,会对请求进行分类,分为简单请求,预先请求,带凭证的请求等,预先请求会首先发送一个 options 探测请求,和浏览器进行协商是否接受请求。默认状况下跨域请求是不须要凭证的,可是服务端能够配置要求客户端提供凭证,这样就能够有效避免 csrf 攻击。
好了,这个问题就说这么多,关于 Spring Boot 中的 CORS ,松哥还有一个小小的视频教程
关注公众号【江南一点雨】,专一于 Spring Boot+微服务以及先后端分离等全栈技术,按期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!