⼀、了解同源政策
在前后端分离架构中,前端请求后端服务器资源时,浏览器端可能会发⽣如下错误:
这种问题我们称之为“跨域”问题。跨域问题来⾃于浏览器同源策略(Same-Origin-Policy)。
同源策略是浏览器⼀项⾮常基础的安全机制,⽤于限制⼀个⽹⻚⽂档或脚本如何与来⾃不同源的资源进⾏交互。简单来说就是,在⼀个源的⽹⻚中,不能向另⼀个源的资源发送Ajax请求。
何为同源?
同源指的是两个URL的协议、域名、端⼝,完全⼀致。两个URL中,三项中只要有⼀项不⼀致,那么就称两个资源是不同源的。那么在⼀个资源中访问另外⼀个资源就会受到浏览器的“跨域限制”。
URL | 说明 | 是否允许通信 |
http://www.domain.com/lab/c.js | 同域名,只是⽂件路径不同 | 允许 |
http://www.domain.com/b.js | 同域名,不同端⼝ | 不允许 |
https://www.domain.com/a.js | 同域名,同端⼝,不同协议 | 不允许 |
域名和域名对应相同IP | 不允许 | |
http://www.domain2.com/b.js | 不同域名 | 不允许 |
URL 说明 是否允许通信
同源策略的作⽤
同源策略的作⽤是保护⽤户的隐私和安全,它可以防⽌恶意⽹站通过脚本访问其他⽹站的敏感信息或进⾏恶意操作。
如果浏览器没有安全策略,我们的⽹站可以加载并执⾏别⼈任意的⽂件,这样的情况将会出现很多不可控的问题。
例如,打开⼀个银⾏站点,然后⼜不⼩⼼打开了⼀个恶意站点,如果没有安全措施,恶意站点就可以做很多事情:
1.修改银⾏站点的DOM、CSSOM等信息
2.在银⾏站点内插⼊恶意JavaScript脚本
3.劫持⽤户登录的⽤户名和密码
4.读取⽤户的Cookie、IndexDB等数据
...
同源策略的影响
浏览器同源策略虽然很⼤程度保护了⽤户的安全,但不得否认的是,同源策略的存在对于⼀些正常项⽬的开发也造成了影响。
例如,在前后端分离架构中,前端系统和后端系统往往是分别部署在不同的物理服务器上的,即使是部署在同⼀台 服务器,通常也会启动在不同的端⼝号。⽽前后端分离架构中,前端发送的所有请求⼏乎都是Ajax异步请求,所以 对服务器资源的访问会受到浏览器的限制。
⼆、在springboot中的跨域解决⽅案
1、在Controller上添加注解@CorssOrigin
@CrossOrigin
@RestController
public class HelloController {
}
Controller上添加了该注解之后,该Controller下的所有⽅法(所有接⼝)都允许跨域访问。 每个Controller都需要配置,较为繁琐。 了解即可,不常⽤。
2、使⽤WebMvcConfigure定义跨域配置
WebMvcConfigure是SpringMVC中⽤来定义Web相关配置的接⼝,通过实现该接⼝,可以配置Web容器中的组 件或资源。例如拦截器、视图控制器、静态资源处理器、视图解析器、跨域配置等等。 使⽤WebMvcConfigure接⼝的步骤
1)定义⼀个类,实现该接⼝
2)添加Configuration注解,使该类成为配置类
3)重写addCorsMappings⽅法,定义跨域相关配置 内容如下:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
// 配置允许跨域访问的资源,/**表示允许访问所有资源
.addMapping("/**")
// 配置允许跨域访问的源
.allowedOrigins("*")
// 配置允许跨域访问使⽤的请求⽅法
.allowedMethods("GET", "POST", "DELETE",
"PUT", "HEAD", "PATCH", "OPTIONS")
// 配置允许跨域访问携带的头部
.allowedHeaders("*")
// 配置是否允许携带Cookie
.allowCredentials(false)
// 配置预检缓存有效时间
.maxAge(3600);
}
}
4)如果项⽬中不包含SpringWeb依赖(例如⽹关Gateway,与SpringWeb冲突),也可以使⽤其他过滤器
3、yml全局跨域配置
# 全局跨域配置
globalcors:
# 解决Options请求被拦截问题(跨域预检请求)
add-to-simple-url-handler-mapping: true
# 所有跨域配置⽅案
corsConfigurations:
# 对所有资源请求进⾏拦截
'[/**]':
# 允许跨域访问的客户端IP
allowedOrigins:
- "*"
# 允许使⽤的HTTP请求⽅法
allowedMethods:
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
# 允许携带的头部字段
allowedHeaders: "*"
# 是否允许携带Cookie
allowCredentials: false
# 跨域缓存有效期(单位:秒)
maxAge: 3600