同源策略和CORS跨源资源共享

浏览器出于安全性考虑,有一个最基本的同源策略 限制了网站和不同源的资源进行交互。但是也有相应的解决方案:跨域资源共享(CORS)

同源策略

源的定义

如果两个URL的协议、端口和主机都相同的话,这两个URL是同源的。相反,如果有一个不同那么就是不同源的。

下面的表给出了和URLhttp://demo.com/dir/page.html进行比对的示例

URL 结果 原因
demo.com/dir/test.ht... 同源 只有路径不同
demo.com/dir/inner/p... 同源 只有路径不同
demo.com/dir/page.ht... 不同源 协议不同
demo.com:8080/dir/page.ht... 不同源 端口不同
test.demo.com/dir/page.ht... 不同源 主机不同

源的继承

通过页面脚本(比如Window.open()等API)打开的about:blankjavascriptURL会继承父脚本的源

data:URL会有一个新的、空的上下文

文件协议

通过文件协议file://加载的文件视为不透明来源,在发送网络请求时,Origin字段会是null值。

而在这些文件加载同目录文件时,有些浏览器可能会将这些同目录文件视为同源文件,这些就取决于浏览器实现了

更改源(已弃用)

通过赋值document.domain可以把当前页面的源修改为当前域或者当前域的父域

比如一个URL是http://test.demo.com的页面,可以在页面执行以下js来修改源

ini 复制代码
document.domain = 'http://demo.com'

网络访问

一般来说,嵌入跨域资源是允许的,比如iframe、css、图片、视频、音频,但是不允许读取这些资源。

对于XMLHttpRequest或是Fetch,同源策略并不是限制了请求发出,而是限制了页面获取请求的响应。

CORS

CORS的基本思想是:客户端在发送请求时携带一个origin表明请求源,然后服务器在跨域请求中提供一个响应头,指示哪些源可以访问资源。

基本工作原理

第 1 步:客户端(浏览器)请求

当浏览器发出跨源请求时,浏览器会添加一个 Origin 标头,其中包含当前源站(架构、主机和端口)。

第 2 步:服务端响应

在服务器端,当服务器看到此标头并希望允许访问时,需要将 Access-Control-Allow-Origin 标头添加到用于指定请求来源的响应中( * 表示允许任何来源,但是在涉及身份凭证时不允许设置)。

第 3 步:浏览器收到响应

当浏览器看到此响应带有相应的 Access-Control-Allow-Origin 标头时,就会允许与客户端网站共享响应数据。

预检请求

简单请求

简单请求不会触发预检请求,但是还是会有同源策略的限制。

简单请求的条件如下

  • 使用的请求方法为 GET、HEAD、POST;
  • 使用的请求头只能是一些浏览器默认设置的头部,比如:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type,但只限于以下三种:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

复杂请求

而当浏览器需要发送一个复杂请求到不同源的服务端时,就会在实际请求消息发送之前先发送一个options请求方法的预检请求,如下

bash 复制代码
OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

而服务器则需要响应预检请求并且提供CORS相关的标头信息

服务器还可以响应Access-Control-Max-Age标头用于指定缓存预检结果的有效期(以秒为单位),这样客户端就不需要每次发送复杂请求都发出预检请求

附带身份凭证的请求

跨域请求默认是不会携带身份凭证信息的。需要设置XMLHttpRequest对象的withCredentials属性为true,或者是fetch请求的credentials选项为'include'

在响应附带身份凭证或者需要设置Set-Cookie响应标头的跨域请求时:

  • Access-Control-Allow-OriginAccess-Control-Allow-HeadersAccess-Control-Allow-Methods这三个CORS响应头都不能设置为*通配符
  • 响应中携带Access-Control-Allow-Credentials:true

CORS响应标头字段

Access-Control-Allow-Origin

指定允许访问源

Access-Control-Allow-Methods

指定允许访问的请求方法

Access-Control-Allow-Headers

用于预检请求的响应,指定实际请求允许携带的标头

Access-Control-Expose-Headers

在跨源访问时,浏览器脚本默认只能拿到基本的响应头:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器在该响应头进行设置

Access-Control-Max-Age

指定预检请求的结果能被缓存多久

Access-Control-Allow-Credentials

指定当浏览器的credentials设置为true时是否允许浏览器读取response的内容。

如果是对预检请求响应的,则指定实际请求是否可以使用credentials

CORS请求标头字段

这些请求标头字段无需手动设置,浏览器会自动设置

Origin

表明请求源

Access-Control-Request-Method

用于预检请求表明实际请求所用的方法

Access-Control-Request-Headers

用于预检请求表明实际请求所携带的字段

相关推荐
恋猫de小郭4 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了12 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅12 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅12 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅12 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment12 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端