Spring Boot 通过CORS实现跨域
同源策略
很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略。
同源策略是由 Netscape 提出的一个著名的安全策略,它是浏览器最核心也最基本的安全功能,现在所有支持 JavaScript 的浏览器都会使用这个策略。所谓同源是指协议、域名以及端口要相同。同源策略是基于安全方面的考虑提出来的,这个策略本身没问题,但是我们在实际开发中,由于各种原因又经常有跨域的需求,传统的跨域方案是 JSONP,JSONP 虽然能解决跨域但是有一个很大的局限性,那就是只支持 GET 请求,不支持其他类型的请求,而今天我们说的 CORS(跨域源资源共享)(CORS,Cross-origin resource sharing)是一个 W3C 标准,它是一份浏览器技术的规范,提供了 Web 服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,这是 JSONP 模式的现代版。
实践
首先,我们新建两个工程:
新建工程一:cors1 project

勾选Web模块 因为我们等下需要通过web接口进行测试 点击Finish完成构建

在cors1 中 我们新建一个HelloController,写上一个测试接口:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello cors1";
}
}
新建工程二:cors2 project

对应的勾选Web模块进行构建。
在cors2的static目录下,建立Index.html,并编写一个GET请求按钮,发起Ajax请求(前提:static目录下有jquery.js)
请求cors1 工程的 localhost:8080/hello接口
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="jquery3.3.1.js"></script>
</head>
<body>
<div id="app"></div>
<input type="button" value="GET" onclick="getData()">
<input type="button" value="PUT" onclick="putData()">
<script>
function getData() {
$.get("http://localhost:8080/hello",function (msg) {
$("#app").html(msg);
})
}
</script>
</body>
</html>
并设定cors2 工程的项目端口:
server.port = 8081
分别启动cors1 和 cors2
访问 localhost:8081/index.html 点击按钮,发送请求:

访问报错,目前不支持跨域,验证了上面说的 同源策略
解决方案一:
1.在Controller类 或 接口方法上,使用 注解 @CrossOrigin 指定允许哪个域服务器访问
@RestController
public class HelloController {
@GetMapping("/hello")
@CrossOrigin(origins = "http://localhost:8081")
public String hello(){
return "hello cors1";
}
}
重启 Cors1 项目,点击发送请求:
访问成功,浏览器控制台也没有报错

注意:
这种方式有一个弊端,就是我们需要在对外开放的每个接口或者类上都要写一遍,大大增加了开发的重复性和繁琐性
解决方案二
Spring Boot 中,可以通过全局配置一次性解决这个问题,全局配置只需要在 SpringMVC 的配置类中重写 **addCorsMappings **方法即可
package org.taoguoguo;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author taoguoguo
* @description WebMvcConfig
* @website https://www.cnblogs.com/doondo
* @create 2020-09-01 21:31
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 跨域全局配置
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
//addMapping 允许哪些接口跨域
//allowedOrigins 允许哪个域服务器访问
//allowedHeaders 允许通过的请求头
//maxAge 服务器在发送一些请求(例如put)会先发一个探测请求,避免每次都需要发送探测请求 可以设置有效期
registry.addMapping("/**")
.allowedOrigins("http://localhost:8081")
.allowedHeaders("*")
.allowedMethods("*")
.maxAge(30*1000);
}
}
/** 表示本应用的所有方法都会去处理跨域请求,allowedMethods 表示允许通过的请求数,allowedHeaders 则表示允许的请求头。经过这样的配置之后,就不必在每个方法上单独配置跨域了
现在再去页面访问,也是没有问题的

探测请求
我们在跨域设置中
maxAge 服务器在发送一些请求(例如put)会先发一个探测请求,避免每次都需要发送探测请求 可以设置有效期
先举一个例子:
我们在Cors1中添加一个put请求
@RestController
public class HelloController {
@GetMapping("/hello")
@CrossOrigin(origins = "http://localhost:8081")
public String hello(){
return "hello cors1";
}
@PutMapping("/doput")
public String doput(){
return "doput";
}
}
在cors2中增加put请求发送按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="jquery3.3.1.js"></script>
</head>
<body>
<div id="app"></div>
<input type="button" value="GET" onclick="getData()">
<input type="button" value="PUT" onclick="putData()">
<script>
function getData() {
$.get("http://localhost:8080/hello",function (msg) {
$("#app").html(msg);
})
}
function putData() {
$.ajax({
type:'put',
url: 'http://localhost:8080/doput',
success:function (msg) {
$("#app").html(msg);
}
})
}
</script>
</body>
</html>
启动cors1 cors2 发送put请求:

我们看到请求一次 浏览器会发送两次请求,其中Request Methods 为 options 的即为探测请求
因为我们设置了探测请求的有效期,因此当我们再次发送时,浏览器只会发送一次请求

了解了整个 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接口发生的跨域问题
最近要重构一个基于spring boot的后端API服务,需要再本地测试.在本地测试时,运行在本地的前端页面发送一个ajax请求访问后端API,然后浏览器报错blocked CORS policy. ...
- Spring Boot+AngularJS中因为跨域导致Session丢失
http://blog.csdn.net/dalangzhonghangxing/article/details/52446821 如果还在为跨域问题烦恼,请查看博主的 解决angular+sprin ...
- Spring MVC使用Cors实现跨域
在开发APP过程中,APP调用后端接口有跨域的问题,只要在spring-mvc.xml 文件中加入下面的配置即可: <!-- 解决API接口跨域问题配置 Spring MVC 版本必须是 4.2 ...
- spring boot 中通过CORS实现跨域
一.跨域问题出现的原因 出现跨域问题的原因是同源策略. 同源策略 主要是三同:同协议.同域名.同端口, 同源策略目的 保证用户信息安全,防止恶意网站窃取数据.同源策略是必须的,否则cookie可以共享 ...
- Spring Boot中通过CORS解决跨域问题
今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由Netscap ...
- spring boot:解决cors跨域问题的两种方法(spring boot 2.3.2)
一,什么是CORS? 1,CORS(跨域资源共享)(CORS,Cross-origin resource sharing), 它是一个 W3C 标准中浏览器技术的规范, 它允许浏览器向非同一个域的服务 ...
- Spring Boot2 系列教程(十四)CORS 解决跨域问题
今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由 Netsca ...
- SpringBoot配置Cors解决跨域请求问题
一.同源策略简介 同源策略[same origin policy]是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源. 同源策略是浏览器安全的基石. 什么是源 源[or ...
- 前后端分离 开发环境通过CORS实现跨域联调
通过JSONP实现跨域已是老生常谈,JSONP跨域限制多,最近了解了一下CORS. 参考: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Acce ...
随机推荐
- 5.19 省选模拟赛 小B的夏令营 概率 dp 前缀和优化dp
LINK:小B的夏令营 这道题是以前从没见过的优化dp的方法 不过也在情理之中. 注意读题 千万不要像我这个sb一样 考完连题意都不知道是啥. 一个长方形 要求从上到下联通的概率. 容易发现 K天只是 ...
- 4.26 ABC F I hate Matrix Construction 二进制拆位 构造 最大匹配
LINK:I hate Matrix Construction 心情如题目名称. 主要说明一下构造的正确性. 准确来说这道题困扰我很久. 容易发现可以拆位构造. 这样题目中的条件也比较容易使用. 最后 ...
- 华为手机内核代码的编译及刷入教程【通过魔改华为P9 Android Kernel 对抗反调试机制】
0x00 写在前面 攻防对立.程序调试与反调试之间的对抗是一个永恒的主题.在安卓逆向工程实践中,通过修改和编译安卓内核源码来对抗反调试是一种常见的方法.但网上关于此类的资料比较少,且都是基于AOSP ...
- QueryRunner使用总结
使用JDBC技术是一件繁琐的事情,为了使数据库更加高效,有一种简化jdbc技术的操作--DBUtils.DbUtils(org.apache.commons.dbutils.DbUtils)是Apac ...
- Mybais面试题(一)
1.对于Hibernate和MyBatis的区别与利弊,谈谈你的看法 Hibernate与MyBatis的对比: 1.MyBatis非常简单易学,与Hibernate相对较复杂,门槛较高; ...
- JS中escape()、encodeURI()、encodeURIComponent()区别详解
avaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decode ...
- 集合:List接口的实现类(ArrayList、LinkedList、Vector)
1.List接口 (1)特点 有序(插入和取出的顺序相等,因为有一个整数索引记录了元素的插入的位置) 允许有重复的元素(调用equals方法返回true,允许有多个null) @Test public ...
- python爬取高匿代理IP(再也不用担心会进小黑屋了)
为什么要用代理IP 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人 ...
- MYSQL 按某个字段分组,然后取每组前3条记录
先初始化一些数据,表名为 test ,字段及数据为: SQL执行结果为:每个 uid 都只有 3 条记录. SQL语句为: SELECT * FROM test main WHERE ...
- 语言模型 Language Model (LM)
定义 什么是语言模型,通俗的讲就是从语法上判断一句话是否通顺.即判断如下的概率成立: \[p(\text{今天是周末})>p(\text{周末是今天}) \] 链式法则(chain rule) ...