跨域
什么是跨域?为何会出现跨域问题?
首先了解一下什么叫做域?简单的定义就是 协议、域名、端口都相同叫做域,缺一不可,还有这里的域并不是单指域名。出于安全考虑,浏览器规定了一种同源策略
。这里的源可以理解为域。
同源策略 的产生是处于安全考虑的。我们都知道,以 Http
协议为例,Http
协议是无状态的,所以我们为了保留某些用户的信息采用了 Cookie
方法,现在的 H5
还有 LocalStorage
。设想一下如果你登录了我的博客,必然会在头部信息中带有登录 Cookie
信息,如果没有同源策略的话,你访问其他其他网站的时候就会带上 cookie
信息,访问对方是恶意网站的话,该恶意网站可以通过访问我博客的接口完全获取你的 个人信息或者修改你的信息。
现实中还是需要突破这个策略需求的,所以 W3C
制定了 CORS
标准,全称是”跨域资源共享”(Cross-origin resource sharing
)。
跨域请求共享
目前主流浏览器都是支持 CORS
标准的,所以当你进行跨域请求的时候,浏览器会自动完成整个过程。但是服务器端并不会,所以需要的解决的就是服务器端的问题。这里还有一点注意的就是浏览器会多发出一次 OPTIONS
请求,这个称作预检,用以判断实际发送的请求是否安全,服务端是不需要理会的。
两种请求
简单请求
1 | 1. 请求方法是以下三种方法之一: |
满足以上两种条件的都称之为简单请求,其他的则是非简单请求。浏览器对于这种请求的处理方式也是不一样的。
简单请求响应
对于简单请求,浏览器发出跨域请求的时候,只会简单的在头部加上 Origin
字段,在 Origin
指定的域名服务器响应中,当然是允许跨域的服务器,会多出几个响应字段,都是以 Access-Control-
开头的字段。
Access-Control-Allow-Origin
该字段是必须
的。它的值要么是请求时 Origin
字段的值,要么是一个 *
,表示接受任意域名的请求。
Access-Control-Allow-Credentials
该字段可选
。它的值是一个布尔值,表示是否允许发送 Cookie
。默认情况下,Cookie
不包括在 CORS
请求之中。设为 true
,即表示服务器明确许可,Cookie
可以包含在请求中,一起发给服务器。这个值也只能设为 true
,如果服务器不要浏览器发送 Cookie
,删除该字段即可。
Access-Control-Expose-Headers
该字段可选
。CORS
请求时,XMLHttpRequest
对象的 getResponseHeader()
方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
。如果想拿到其他字段,就必须在 Access-Control-Expose-Headers
里面指定。
非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是 PUT
或 DELETE
,或者 Content-Type
字段的类型是application/json
。
除了简单请求的 Origin
字段外,还有两个特殊的头信息字段:
Access-Control-Request-Method
该字段是必须
的,用来列出浏览器的 CORS
请求会用到哪些 HTTP
方法,上例是 PUT
。
Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器 CORS
请求会额外发送的头信息字段。
非简单请求响应
当服务器发出非简单请求的时候,服务段会响应一下几个头信息:
Access-Control-Allow-Methods
该字段必需
,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。
Access-Control-Allow-Headers
如果浏览器请求包括 Access-Control-Request-Headers
字段,则 Access-Control-Allow-Headers
字段是必需
的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。
Access-Control-Allow-Credentials
该字段与简单请求时的含义相同。
Access-Control-Max-Age
该字段可选
,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。
Lumen 处理跨域请求
回到标题的问题,如果来解决 Lumen
的跨域请求问题。了解 CORS
标准之后,如果你使用 Lumen
框架是基于 restful api
的话,就避免不了 PUT
和 DELETE
请求。
需要建立一下几个响应字段
1 | Access-Control-Allow-Origin: '*' // 允许的域名 |
建立一个 CORS
中间件文件:
1 | namespace App\Http\Middleware; |
在 boostrap\app.php
文件加入中间件
1 | $app->middleware([ |
这样就可以解决跨域问题了