http访问控制(CORS)

前言

前后端分离会带有很多优势,也是当今开发的主流方向,但是也会有些小问题,比如跨域。那什么是跨域呢?很简单的,比如,我在开源中国去访问百度的资源,那就是跨域,只要资源提供方和当前地址不一致就是跨域请求,具体说来就是域名或者ip+port发生了变化。这种机制是浏览器出于安全机制的角度而产生的,防止资源盗窃等行为。所以前后端分开就必须解决这个问题了。

 

2. 跨域解决方案

 

cors

 

全称为 Cross Origin Resource Sharing(跨域资源共享),这是最简单的方式,这种方案对于前端来说没有什么工作量,和正常发送请求写法上没有任何区别,前提是需要后端支持。但是有个缺点是:浏览器必须先以 OPTIONS 请求方式发送一个预请求(也不是所有请求都会发送 options,详解请看链接),通过预检请求从而获知服务器端对跨源请求支持的 HTTP 方法。在确认服务器允许该跨源请求的情况下,再以实际的 HTTP 请求方法发送那个真正的请求。

 

nginx

 

nginx作为中转代理,此种方式也是前后端分离的标准模式之一,在性能和易用性上也是非常友好的。关于如何在nginx上部署前端代码,如何配置等等,可以参见以下文章:

https://cli.vuejs.org/guide/deployment.html#general-guidelines

https://my.oschina.net/u/1760791/blog/1575808

https://juejin.im/post/5c850ff7e51d453a5b0224e3

 

3. cors详解

对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“*”。这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为某个具体的origin,则请求将成功执行。

将 XMLHttpRequest 的 withCredentials 标志设置为 true,从而向服务器发送 Cookies。因为这是一个简单 GET 请求,所以浏览器不会对其发起“预检请求”。但是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true ,浏览器将不会把响应内容返回给请求的发送者。

跨域访问响应头:

Access-Control-Allow-Origin

参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。

Access-Control-Expose-Headers

在跨域访问时,XMLHttpRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头。

让服务器把允许浏览器访问的头放入白名单,例如:

Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header

这样浏览器就能够通过getResponseHeader访问X-My-Custom-Header和 X-Another-Custom-Header 响应头了。

Access-Control-Max-Age

参数表示preflight请求的结果在多少秒内有效。

Access-Control-Allow-Credentials

指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容。当用在对预检测请求的响应中时,它指定了实际的请求是否可以使用credentials。请注意:简单 GET 请求不会被预检;如果对此类请求的响应中不包含该字段,这个响应将被忽略掉,并且浏览器也不会将相应内容返回给网页。

Access-Control-Allow-Methods

用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。

Access-Control-Allow-Headers

其指明了实际请求中允许携带的首部字段。

跨域访问请求头:

请注意,这些首部字段无须手动设置。 当开发者使用 XMLHttpRequest 对象发起跨域请求时,它们已经被设置就绪。

Origin

origin 参数的值为源站 URI。它不包含任何路径信息,只是服务器名称。不管是否为跨域请求,ORIGIN 字段总是被发送。

Access-Control-Request-Method

将实际请求所携带的首部字段告诉服务器。

广州包装设计公司http://www.maiqicn.com 电脑刺绣绣花厂 ttp://www.szhdn.com

4. XMLHttpRequest

关于XMLHttpRequest,前端的伙伴肯定是非常熟悉的,后端的伙伴可以参考下面的网站,写的很透彻:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest,只是有一点,想要和大家分享以下,那就是缓存。

缓存的问题真的是非常常见。在开发过程中,我们不希望有缓存,因为经常改动代码,希望能够立即看到效果,生产上,又希望有缓存,以此提高响应请求。关于缓存启用和禁用的方法也是多种多样。建议大家阅读下浏览器工作原理:https://juejin.im/entry/5ad86c16f265da505a77dca4,此篇文章图文并茂的解析了缓存原理。

 

在ie11浏览器环境测试下,在get请求下,会发现加各种控制缓存的头都不起作用(可能是我使用错误??),最后的解决方案还是在请求地址后面加上一个随机参数,通常是当前时间戳,最后解决了问题。

http访问控制(CORS)

上一篇:CSS中层叠上下文


下一篇:http中的post请求数据格式