CORS-HTTP 访问控制
CORS 是用来规避 SOP 的。
同源策略等安全策略是浏览器在实行,像node这样的工具是没有遵循的。
同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式。
对于完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题:
- 片段识别符(fragment identifier) // hash, 子窗口也可以改变父窗口
- window.name
- 跨文档通信API(Cross-document messaging)postMessage
跨域和服务端通信,除了架设服务器代理,有三种方法规避这个限制:
- JSONP // 资源没有跨域问题,要跨域读取资源内容(如错误)的话也需要 CORS 设置
- WebSocket:WebSocket是一种通信协议,该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
- CORS
响应头名称不区分大小写,但是值区分(?)
请求头中的Origin值是小写,但是跨源控制的响应头中域名大小写敏感
// Origin头与CORS请求一起发送,以及POST请求。不能自行设置
同域:协议:主机(子域):端口
跨源资源共享 (Cross-Origin Resource Sharing, CORS),需要支持跨源共享带来的新的组件,包括请求头和策略执行。同样,服务器端则需要解析这些新的请求头,并按照策略返回相应的响应头以及所请求的资源。
跨域并非浏览器限制了发起跨站请求,而是跨站请求可以正常发起,但是返回结果被浏览器拦截(没有允许跨域响应头)了。最好的例子是 crsf 跨站攻击原理,请求是发送到了后端服务器无论是否跨域!
进行跨域非简单请求时,浏览器会自动发送 Options 请求。所谓的简单,是指:
- 只使用 GET, HEAD 或者 POST 请求方法。如果使用 POST 向服务器端传送数据,则数据类型(Content-Type)只能是 application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种。
- 不会使用自定义请求头(类似于 X-Modified 这种,content-type 等不是自定义请求头)。
"预请求"要求必须先发送一个 OPTIONS 请求给目的站点,OPTIONS 是 HTTP/1.1 里的方法,用来获取更多服务器端的信息,是一个不应该对服务器数据造成影响的方法。这样做,是因为跨站请求可能会对目的站点的数据造成破坏。非简单请求会被当做预请求处理。服务器响应options请求中带Access-Control-Allow-Methods,Access-Control-Max-Age(options请求结果有效时间)等字段,浏览器根据响应来觉得是否发送该非简单请求。
尽管不通过 CORS 就可以在画布中使用图片,但是这会污染画布。一旦画布被污染,你就无法读取其数据。例如,你不能再使用画布的 toBlob(), toDataURL() 或 getImageData() 方法,调用它们会抛出安全错误。
这种机制可以避免未经许可拉取远程网站信息而导致的用户隐私泄露。
脚本也有 crossorigin 属性,使用此属性且服务器能响应正确的响应头 Access-Control-Allow-Origin 那么这个js的脚本错误能显示详细信息(行列) 。
语法:一个源 或 *
Access-Control-Allow-Origin: | *
(使用通配符就不能带 credentials,加 access-control-allow-credentials 响应头也不行)
跨源资源共享标准( cross-origin sharing standard ) 使得以下场景可以使用跨站 HTTP 请求:
- 如上所述,使用 XMLHttpRequest 发起跨站 HTTP 请求。
- Web 字体 (CSS 中通过 @font-face 使用跨站字体资源), 因此,网站就可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用。
- WebGL 贴图
- 使用 drawImage API 在 canvas 上画图(即上述)
一般而言,对于跨站xhr请求,浏览器是不会发送凭证信息(cookie)的。但如果将XMLHttpRequest的一个特殊标志位(withCredentials)设置为true,浏览器就将允许该凭证的发送。但是,如果服务器端的响应中,如果没有返回Access-Control-Allow-Credentials: true的响应头,那么浏览器将不会把响应结果传递给发出请求的脚步程序,以保证信息的安全。