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

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

相关推荐
甜兒.29 分钟前
鸿蒙小技巧
前端·华为·typescript·harmonyos
Jiaberrr4 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy4 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白4 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、4 小时前
Web Worker 简单使用
前端
web_learning_3214 小时前
信息收集常用指令
前端·搜索引擎
tabzzz5 小时前
Webpack 概念速通:从入门到掌握构建工具的精髓
前端·webpack
200不是二百5 小时前
Vuex详解
前端·javascript·vue.js
滔滔不绝tao5 小时前
自动化测试常用函数
前端·css·html5
码爸5 小时前
flink doris批量sink
java·前端·flink