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:

复杂请求

不符合简单请求的情况为复杂请求,请求流程如下:

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.comb.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 the Authorization header can't be wildcarded and always needs to be listed explicitly.

Chrome 手动改 Cookies

Chrome 手动改 Cookies,设置给一级域名时,应该写作 .domain.com 而不是 domian.com

跨域怎么解决?

跨域问题是由于浏览器的同源策略造成的。同源策略是一个重要的安全策略,它防止了一些恶意行为,如跨站请求伪造(CSRF)。然而,它也对合法的跨源请求造成了阻碍。

解决跨域问题的常用方法包括:

  1. CORS(跨源资源共享):这是一种官方推荐的解决方式,需要服务器端进行一些配置,以允许特定的外部域进行访问。服务器可以在响应头中包含一个 "Access-Control-Allow-Origin" 字段,以指定哪些域可以接收响应。
  2. JSONP(JSON with Padding):JSONP 是一个传统的跨域解决方案,它利用了 <script> 标签没有同源限制的特性。这种方法虽然被广泛使用,但也存在一些安全问题。
  3. 使用代理服务器:可以在同源的服务器端设置一个代理服务器,由代理服务器进行外部请求,然后将结果返回给前端。因为代理服务器和前端在同一域,所以不存在跨域问题。
  4. WebSockets:WebSockets不受同源策略的限制,所以可以用于跨域通信。
  5. PostMessage:HTML5引入的一种新的API,允许跨窗口通信,不受同源策略限制。
  6. Document.domain:这种方法只适用于二级域名相同的情况下。

请注意,除 CORS 外,其他方法可能存在一些安全问题,或者在一些特定情况下可能不适用。在进行跨域访问时,应优先考虑使用 CORS。

另外,关于下载文件的跨域问题,由于安全性和隐私性考虑,浏览器通常不允许跨域下载文件。即使使用上述的跨域解决方案,也很难直接实现 <a href="..." download> 的跨域下载功能。如果要下载跨域的文件,你可能需要通过服务器端进行中转,或者使用其他技术(例如通过 AJAX 获取数据,然后在浏览器端生成 Blob 对象并下载)。

超链接加上 download 属性

在HTML中,当你希望点击超链接时自动下载链接资源,而不是在浏览器中打开它,你可以在<a>标签中加上download属性。

例如:

html
1<a href="path_to_file" download>点击这里下载</a>

当你点击“点击这里下载”,浏览器将尝试下载在href属性中指定的文件。

你也可以给download属性指定一个值,这个值将作为下载文件的默认文件名(如果用户没有在保存对话框中改变它):

html
1<a href="path_to_file" download="myFile">点击这里下载</a>

在这个例子中,点击链接将尝试下载path_to_file并将其命名为myFile

请注意,此属性仅适用于同源URL。它不会对跨域的资源起作用。此外,并非所有浏览器都支持此属性,尤其是一些老旧的浏览器可能无法使用此功能。

通过 AJAX 获取数据,然后在浏览器端生成 Blob 对象并下载