文章目录
跨域问题
一、什么是 跨域?
当请求url
的协议、域名、端口三者之间任意一个与当前页面url
不同即为跨域。以下都属于跨域:
当前页面url | 被请求页面url | 原因 |
---|---|---|
http://www.test.com/ | https://www.test.com/index.html | 协议不同(http/https ) |
http://www.test.com/ | http://www.baidu.com/ | 主域名不同(test/baidu ) |
http://www.test.com/ | http://blog.test.com/ | 子域名不同(www/blog ) |
http://www.test.com:8080/ | http://www.test.com:7001/ | 端口号不同(8080/7001 ) |
注意:协议、域名和端口都相同,但是请求路径不同,不属于跨域,如:www.jd.com/item
和 www.jd.com/goods
二、什么是 跨域问题?
跨域问题是指一个页面尝试加载来自跨域(协议、域名、端口)的资源时所遇到的限制和问题。
如上图所示,由 http://localhost:8082 向 http://localhost:8088/user/list 发起 AJAX 请求,由于端口不同,产生了跨域问题。
三、为什么有 跨域问题?
为了保证浏览器的安全,不同源的客户端在没有明确授权的情况下,不能读写对方资源,称为同源策略
。
同源策略
是浏览器安全的基石。
四、什么是 同源策略?
同源策略
(Same-Origin Policy)是一种Web安全机制,它定义了浏览器在加载网页时如何限制不同源之间的交互。
所谓同源
(即指在同一个域)就是两个页面具有相同的协议(Protocol),主机(Host)和端口号(Port)
具体来说,同源策略限制了以下内容:
-
JavaScript 访问:一个源的 JS代码 只能访问同源的资源,无法直接访问其他源的资源。
这意味着,一个网页的 JS代码 无法读取/修改其他源的页面内容,包括 Cookie、LocalStorage、SessionStorage 等。
-
DOM 访问:一个网页只能访问同源的DOM(文档对象模型)结构,无法直接访问其他源的DOM。
这意味着,一个网页无法通过 JS代码 操作其他源的DOM,比如向其他源的表单提交数据 或 点击其他源的按钮。
-
AJAX 请求:由于同源策略的限制,JS代码 不能直接通过 XMLHttpRequest对象 向其他源发起 AJAX请求。
这意味着,一个网页无法通过 AJAX请求 获取其他源的数据,除非其他源明确允许跨域请求(通过CORS等方式)。
因此,跨域不一定有跨域问题,跨域问题是违反了同源策略的限制而产生的。(一般是AJAX请求
获取跨域数据导致的)
五、为什么需要 同源策略?
同源策略
的存在是为了保护用户的隐私和安全,防止恶意网站通过 JS代码 获取用户的敏感信息或者进行CSRF(跨站请求伪造)攻击。
可以说 同源策略
是浏览器安全的基石。
但同时 同源策略
也带来了一些限制,需要开发者在设计网站时考虑如何合理地处理跨域访问的问题。
六、怎么解决 跨域问题?
1、CORS 简介
CORS(Cross-Origin Resource Sharing)跨域资源共享,是由W3C制定的一种跨域资源共享技术标准。
CORS 可以在不破坏即有规则的情况下,通过 浏览器 与 服务器 之间的交互, 实现跨域通信。
- 浏览器 发起 AJAX请求 时,在 请求头 携带请求的信息,以此来询问 服务端 是否允许当前网站的跨域请求。
- 服务端 接收到 浏览器 的请求后,会对请求信息做出判断,如果允许,就在 响应头 中携带一些许可的声明。
- 浏览器 根据 服务端 的响应做出 拦截 或 放行 的处理。
这样,CORS 允许 浏览器 向 跨源服务器 发出 XMLHttpRequest 请求,从而克服了AJAX只能 同源 使用的限制。
2、CORS 请求分类
CORS 将请求分为两类:简单请求
和 非简单请求
,分别对跨域通信提供了支持。
满足以下条件的请求,即为 简单请求:
- 请求方法:GET、POST、HEAD
- 请求头:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type
- Content-Type:text/plain、multipart/form-data、application/x-www-form-urlencoded
如果不满足以上条件,即为 非简单请求。
3、简单请求
对于简单请求,CORS的策略是请求时在请求头中增加一个 Origin
字段
服务器收到请求后,判断该源是否允许跨域,如果允许,则在响应头中添加 Access-Control-Allow-Origin
字段
4、非简单请求
对于非简单请求的跨源请求,浏览器会在真实请求发出前增加一次 OPTION 请求,称为预检请求(pre flight request)
Origin
:源信息Access-Control-Request-Method
:表示 请求方式Access-Control-Request-Headers
:包含 简单请求 以外的请求头信息。
服务器收到请求时,需要对 Origin、Access-Control-Request-Method、Access-Control-Request-Headers 等进行验证
验证通过后,会在响应头中添加相关信息:
Access-Control-Allow-Origin
:允许哪些网站的跨域请求Access-Control-Allow-Methods
:允许跨域的请求方式Access-Control-Allow-Headers
:允许在请求中携带的头信息Access-Control-Allow-Credentials
:是否允许用户发送、处理cookieAccess-Control-Max-Age
:预检请求的有效期,单位为秒,有效期内不会重复发送预检请求。
当预检请求通过后,浏览器才会发送真实请求到服务器。这样就实现了跨域资源的请求访问。
七、SpringBoot 解决跨域问题
1、局部配置
将 @CrossOrigin
注解加载对应的 Controller 上,这样对应的 Controller 中的所有方法都允许跨域
@CrossOrigin
@RestController
public class UserController {
// ...
}
2、全局配置
使用配置类,对所有控制器生效
/**
* Cors解决跨域问题
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "Options", "DELETE", "PUT")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(16800);
}
}
八、SpringCloud 解决跨域问题
在 SpringCloud Gateway 中,已经提供了默认的CORS实现,我们只需要通过 application.yml 做简单配置即可。
spring:
cloud:
gateway:
# 全局的跨域处理
globalcors:
# 是否将当前cors配置加入到SimpleUrlHandlerMapping中,解决options请求被拦截问题
add-to-simple-url-handler-mapping: true
# cors配置
cors-configurations:
# 拦截所有
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求(尽量使用域名)
- "http://www.taobao.com"
- "http://www.baidu.com"
allowedMethods: # 允许的的请求方式(*表示全部)
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息(*表示全部)
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 跨域检测的有效期