同源策略和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

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

相关推荐
原谅我很悲23 分钟前
实际开发中,前端项目安装依赖问题总结
前端
humors2211 小时前
java实现excel导入参考资料合集
java·前端·后端·wps·导出·导入·office
New.file2 小时前
AJAX详解
前端·ajax·okhttp
小七蒙恩3 小时前
java 上传txt json等类型文件解析后返回给前端
java·前端·json
糕冷小美n3 小时前
jeecgbootvue3列表数据状态为数字时,手动赋值的三种方法
前端·javascript·vue.js
mqiqe3 小时前
Nginx 配置前端后端服务
运维·前端·nginx
小羊小羊,遇事不难5 小时前
Error: near “112136084“: syntax
java·服务器·前端
Domain-zhuo5 小时前
CSS实现一个自定义的滚动条
前端·javascript·css·vue.js·git·node.js
autumn8685 小时前
css的长度单位有那些?
前端·css
李贺梖梖5 小时前
CSS2笔记
前端