同源策略和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小郭36 分钟前
Flutter 3.35 发布,快来看看有什么更新吧
android·前端·flutter
chinahcp20082 小时前
CSS保持元素宽高比,固定元素宽高比
前端·css·html·css3·html5
gnip3 小时前
浏览器跨标签页通信方案详解
前端·javascript
gnip3 小时前
运行时模块批量导入
前端·javascript
hyy27952276843 小时前
企业级WEB应用服务器TOMCAT
java·前端·tomcat
逆风优雅3 小时前
vue实现模拟 ai 对话功能
前端·javascript·html
若梦plus4 小时前
http基于websocket协议通信分析
前端·网络协议
不羁。。4 小时前
【web站点安全开发】任务3:网页开发的骨架HTML与美容术CSS
前端·css·html
这是个栗子4 小时前
【问题解决】Vue调试工具Vue Devtools插件安装后不显示
前端·javascript·vue.js
姑苏洛言4 小时前
待办事项小程序开发
前端·javascript