基于Chrome插件实现支持CORS的本地开发代理

什么是跨域

跨域:因为浏览器的同源策略,属于不一样域的页面之间不能相互访问各自的页面内容。web

开发中后台项目,咱们首先须要让本地服务run起来,起一个如http://localhost:8000/scg/show这样的页面,而后,当咱们须要进行网络交互时,一般使用相对域名,如/scg/search.json?pageNo=1, 假设项目的代理配置以下chrome

undefined

那么当请求/scg/search.json?pageNo=1时,代理转发出去的请求的是http://ottscg.alibaba.net/scg/search.json?pageNo=1, localhost去请求ottscg.alibaba.net中的内容,这时就发生了跨域。json

CORS跨域发送 Cookie

浏览器经过代理发出CORS请求时,会在头信息之中,增长一个Origin字段,表示本次请求来自哪一个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否赞成此次请求。若是Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。跨域

若是Origin指定的域名在许可范围内,服务器返回的响应,会多出几个以"Access-Control"开头的头信息字段,为了发送带cookie的跨域请求,咱们首先须要关心的是Access-Control-Allow-OriginAccess-Control-Allow-Credentials浏览器

Access-Control-Allow-Origin

这个头是容许CORS时,必须返回的头,它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。bash

Access-Control-Allow-Credentials

默认状况下浏览器对跨域请求不会携带 Cookie,但鉴于 Cookie 在身份验证等方面的重要性, CORS 推荐使用额外的响应头字段来容许跨域发送 Cookie。 这是一个可选的头,若发送带cookie的请求,则必须返回这个头,并设置为true,表示服务器容许客户端发送Cookie。   须要注意的是,这个头被设置为true时,Access-Control-Allow-Origin不容许使用*,并且只能指定单一域名,不然浏览器会报以下错误。服务器

undefined

综上, 发送cookie的CORS的正确姿式是:cookie

  • 客户端为fetch配置 credentials 项:credentials: 'include';
  • 服务端返回的responseHeader中携带以下两个头信息字段
    Access-Control-Allow-Origin: Origin;
    Access-Control-Allow-Credentials : true
    复制代码

The include part tells Chrome that you want to send a CORS request to the server which sends along the cookies properly网络

Chrome插件里怎么作

经过了解CORS原理,咱们知道了不支持CORS的服务端会返回一个正常的HTTP回应,只是因为没有Aceess-control相关的响应头,致使浏览器对响应进行了拦截。利用chrome.webRequest API,对onHeadersReceived进行监听,便可在每次接收到 HTTP(S) 响应标头时,添加须要的header字段,让浏览器觉得这些头信息是服务端返回的,从而绕过CORS限制。app

//Breaking the CORS Limitation
chrome.webRequest.onHeadersReceived.addListener(details=>window.onHeadersReceivedCallback(details), {
  urls: ['<all_urls>']
}, ["blocking", "responseHeaders"]);
复制代码

简单请求和复杂请求

只设置Access-Control-Allow-Origin和Access-Control-Allow-Crendentials两个字段,并不能知足全部的场景。例如,咱们在使用Antd的Upload组件进行上传图片时,Chrome会报以下错误:

undefined

Preflight

Access-Control-Allow-Origin响应头字段能够容许跨域 AJAX, 但对于非简单请求,CORS 机制跨域会首先进行 preflight(一个 OPTIONS 请求,表示这个请求是用来询问的)

undefined

简单请求

具体是指请求方法是简单方法且请求头是简单头的 HTTP 请求。具体地,

  • 简单方法包括GET, HEAD, POST。
  • 简单头包括:Accept, Accept-Language, Content-Language,以及值为application/x-www-form-urlencoded, multipart/form-data, text/plain 其中之一的 Content-Type 头。 对于非简单请求浏览器会首先发送 OPTIONS 请求(成为 preflight)

Access-Control-Request-Headers

Access-Control-Request-Headers 是 preflight 请求中用来标识真正请求将会包含哪些头部字段, 例以下述请求中Access-Control-Request-Headers字段的值是x-requested-with,告知服务器,实际请求将携带这个自定义请求首部字段。服务器据此决定,该实际请求是否被容许,若是容许,服务器应当在对应的Access-Control-Allow-Headers响应头中包含这个字段。 不然即便返回 200 preflight 也会失败。

undefined

查看Antd Upload组件的源码,咱们看到,在上传图片时,增长了x-requested-with请求头,由此触发了非简单请求,会在CORS时先进行Option询问

undefined

综上,为了处理非简单请求下的CORS,除了Access-Control-Allow-Origin和Access-Control-Allow-Crendentials外,咱们还须要在Header劫持中添加以下配置

Access-Control-Allow-Methods:"*",
Access-Control-Allow-Headers:"Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
复制代码
相关文章
相关标签/搜索