Cross-Origin Resource Sharing
Relate to https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
首先不谈 JSONP 这种注入执行动态js的方案。
Simple requests
A simple request is one that meets all the following conditions:
- One of the allowed methods:
- GET
- HEAD
- POST
- Apart from the headers automatically set by the user agent (for example,
Connection
,User-Agent
, or the other headers defined in the Fetch spec as a forbidden header name), the only headers which are allowed to be manually set are those which the Fetch spec defines as a CORS-safelisted request-header, which are:- Accept
- Accept-Language
- Content-Language
- Content-Type
- The only type/subtype combinations allowed for the media type specified in the
Content-Type
header are:application/x-www-form-urlencoded
multipart/form-data
text/plain
- If the request is made using an
XMLHttpRequest
object, no event listeners are registered on the object returned by theXMLHttpRequest.upload
property used in the request; that is, given anXMLHttpRequest
instancexhr
, no code has calledxhr.upload.addEventListener()
to add an event listener to monitor the upload. - No
ReadableStream
object is used in the request.
复杂请求
不符合简单请求的情况为复杂请求,请求流程如下:
1、PUT / DELETE 或者 Content-Type:application/json
类型的请求
2、发出 CORS 请求时,会在正式通信之前增加一次 “预检”请求(OPTIONS 方法),来询问服务器,本次请求的域名是否在许可名单中,以及使用哪些头信息
3、当 “预检”请求 通过以后,才会正式发起 请求,否则报错
头部信息概念
Access-Control-Allow-Origin
:*
设置可以访问的域名,* 表示所有网站都可以访问资源。Access-Control-Allow-Headers
:Origin,Last-Modified, Cache-Control
设置resquest headers
里哪些字段有效Access-Control-Allow-Methods
:POST、GET
允许请求的方式Access-Control-Allow-Credentials
:true
,允许携带Cookie
,同时 AJAX 请求中开启withCredentials
属性,xhr.withCredentials = true
,否则浏览器不会发送Cookie
document.domain
只能用于二级域名相同的情况下,比如 a.test.com
和 b.test.com
适用。
只需要给页面添加 document.domain = 'test.com'
表示二级域名都相同就可以实现跨域
一些需要注意的问题
Access-Control-Allow-Headers 设置为 * 的情况
被 ChatGPT 骗了, 只有 Safari 不支持 *。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
-
<header-name>
The name of a supported request header. The header may list any number of headers, separated by commas.
-
*
(wildcard)The value "
*
" only counts as a special wildcard value for requests without credentials (requests without HTTP cookies or HTTP authentication information). In requests with credentials, it is treated as the literal header name "*
" without special semantics. Note that theAuthorization
header can't be wildcarded and always needs to be listed explicitly.
Chrome 手动改 Cookies
Chrome 手动改 Cookies,设置给一级域名时,应该写作 .domain.com
而不是 domian.com
跨域怎么解决?
跨域问题是由于浏览器的同源策略造成的。同源策略是一个重要的安全策略,它防止了一些恶意行为,如跨站请求伪造(CSRF)。然而,它也对合法的跨源请求造成了阻碍。
解决跨域问题的常用方法包括:
- CORS(跨源资源共享):这是一种官方推荐的解决方式,需要服务器端进行一些配置,以允许特定的外部域进行访问。服务器可以在响应头中包含一个 "Access-Control-Allow-Origin" 字段,以指定哪些域可以接收响应。
- JSONP(JSON with Padding):JSONP 是一个传统的跨域解决方案,它利用了
<script>
标签没有同源限制的特性。这种方法虽然被广泛使用,但也存在一些安全问题。 - 使用代理服务器:可以在同源的服务器端设置一个代理服务器,由代理服务器进行外部请求,然后将结果返回给前端。因为代理服务器和前端在同一域,所以不存在跨域问题。
- WebSockets:WebSockets不受同源策略的限制,所以可以用于跨域通信。
- PostMessage:HTML5引入的一种新的API,允许跨窗口通信,不受同源策略限制。
- Document.domain:这种方法只适用于二级域名相同的情况下。
请注意,除 CORS 外,其他方法可能存在一些安全问题,或者在一些特定情况下可能不适用。在进行跨域访问时,应优先考虑使用 CORS。
另外,关于下载文件的跨域问题,由于安全性和隐私性考虑,浏览器通常不允许跨域下载文件。即使使用上述的跨域解决方案,也很难直接实现 <a href="..." download>
的跨域下载功能。如果要下载跨域的文件,你可能需要通过服务器端进行中转,或者使用其他技术(例如通过 AJAX 获取数据,然后在浏览器端生成 Blob 对象并下载)。
超链接加上 download 属性
在HTML中,当你希望点击超链接时自动下载链接资源,而不是在浏览器中打开它,你可以在<a>
标签中加上download
属性。
例如:
1<a href="path_to_file" download>点击这里下载</a>
当你点击“点击这里下载”,浏览器将尝试下载在href
属性中指定的文件。
你也可以给download
属性指定一个值,这个值将作为下载文件的默认文件名(如果用户没有在保存对话框中改变它):
1<a href="path_to_file" download="myFile">点击这里下载</a>
在这个例子中,点击链接将尝试下载path_to_file
并将其命名为myFile
。
请注意,此属性仅适用于同源URL。它不会对跨域的资源起作用。此外,并非所有浏览器都支持此属性,尤其是一些老旧的浏览器可能无法使用此功能。
通过 AJAX 获取数据,然后在浏览器端生成 Blob 对象并下载