峰哥说技术:18-Spring Boot通过CORS实现跨域请求

Spring Boot深度课程系列

峰哥说技术—2020庚子年重磅推出、战胜病毒、我们在行动

18  峰哥说技术:Spring Boot通过CORS实现跨域请求

对于跨域,必须要说是浏览器的同源策略。同源策略是由Netscape提出的一个著名的安全策略,它是浏览器最核心也最基本的安全功能,现在所有支持JavaScript的浏览器都会使用这个策略。

所谓同源是指协议、域名以及端口要相同。同源策略是基于安全方面的考虑提出来的,这个策略本身没问题,但是我们在实际开发中,由于各种原因又经常有跨域的需求,传统的跨域方案是JSONP,JSONP虽然能解决跨域但是有一个很大的局限性,那就是只支持GET请求,不支持其他类型的请求。

我们说的CORS(跨域源资源共享)(CORS,Cross-origin resource sharing)是一个W3C标准,它是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,这是JSONP模式的现代版。
Spring框架中,对于CORS也提供了相应的解决方案,下面我们看看Spring Boot中如何实现CORS。

步骤:

1)创建Spring Boot项目chapter04-server个,添加web依赖。同时在Application.properties中配置端口。

server.port=8080

2)创建BookController,编写2个测试接口。

@RestController
@RequestMapping("/book")
public class BookController {
    @PostMapping("/")
    public String addBook(String name){
        return "添加"+name;
    }
    @DeleteMapping("/{bookId}")
    public String deleteBook(@PathVariable Integer bookId){
        return "删除书籍:"+bookId;
    }
}

3)配置在接口方法上配置跨域。

@RestController
@RequestMapping("/book")
public class BookController {
    @PostMapping("/")
    @CrossOrigin(value = "http://localhost:8081",maxAge = 1800,allowedHeaders = "*")
    public String addBook(String name){
        return "添加"+name;
    }
    @DeleteMapping("/{bookId}")
    @CrossOrigin(value = "http://localhost:8081",maxAge = 1800,allowedHeaders = "*")
    public String deleteBook(@PathVariable Integer bookId){
        return "删除书籍:"+bookId;
    }
}

4)创建另一个Spring Boot项目chapter04-client,添加web依赖。端口号为8081,工程结构如图:

 

5)chapter04-client的static中添加index.html页面。添加两个按钮,分别是添加图书和删除图书,发送Ajax请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-1.12.4.js"></script>
</head>
<body>
    <input type="button" onclick="insertBook()" value="添加图书"> <br>
    <input type="button" onclick="deleteBook()" value="删除图书">
    <div id="div1"></div>
</body>
<script type="application/javascript">
    function insertBook() {
        $.ajax({
            url:"http://localhost:8080/book/",
            data:{"name":"红楼梦"},
            type:"post",
            success:function (msg) {
               $("#div1").html(msg);
            }
        })
    }
    function deleteBook() {
        $.ajax({
            url:"http://localhost:8080/book/90",
            type:"delete",
            success:function (msg) {
                $("#div1").html(msg);
            }
        })
    }
</script>
</html>

6)测试:在浏览器输入:http://localhost:8081/index.html

 

浏览器调试分析:

 

这里的Access-Control-Allow-Origin: http://localhost:8081表示服务器愿意愿意接收来自http://localhost:8081的请求,拿到这个信息后,浏览器就不会再去限制本次请求的跨域了。

在服务器端,如果每一个方法上都去加注解未免太麻烦了,在Spring Boot中,还可以通过全局配置一次性解决这个问题,全局配置只需要在配置类中重写addCorsMappings方法即可,如下:

步骤:

1)注释方法上的@CrossOrigin注解。

2)编写WebMvcConfig配置类,实现接口WebMvcConfigurer,实现方法public void addCorsMappings(CorsRegistry registry)

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/book/**")
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowedOrigins("http://localhost:8081")
                .maxAge(1800);
    }
}

addMapping("/book/**")表示本应用的所有方法都会去处理跨域请求,allowedMethods表示允许通过的请求方法,默认是GET、POST和HEAD,*表示支持所有的请求方法,allowedHeaders则表示允许的请求头。*表示所有的请求头。allowedOrigins("http://localhost:8081")表示支持的域。经过这样的配置之后,就不必在每个方法上单独配置跨域了。

了解了整个CORS的工作过程之后,我们通过Ajax发送跨域请求,虽然用户体验提高了,但是也有潜在的威胁存在,常见的就是CSRF(Cross-site request forgery)跨站请求伪造。跨站请求伪造也被称为one-click attack 或者 session riding,通常缩写为CSRF或者XSRF,是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

基于此,浏览器在实际操作中,会对请求进行分类,分为简单请求,预先请求,带凭证的请求等,预先请求会首先发送一个options探测请求,和浏览器进行协商是否接受请求。默认情况下跨域请求是不需要凭证的,但是服务端可以配置要求客户端提供凭证,这样就可以有效避免csrf攻击。

原文地址:https://www.cnblogs.com/027kgc/p/12502274.html