之前做了一个公司的内部管理系统,现在希望通过在钉钉上开发一个小应用查看相关资料,其中涉及到HTTP跨域的域请求问题,了解了相关资料后,打算基于CORS来实现。对于CORS(跨源资源共享),请参阅本文。在CORS中,对于一个简单的请求,服务器只需要在验证相关字段后进行响应,主要是验证请求的来源和请求的方法是否被服务器允许。对于复杂的请求,浏览器会先向服务器发送一个选项请求进行验证,验证通过后才发送用户的请求。在options请求中,服务器会返回允许的请求源、请求方法、头字段等。Laravel中CORS的实现,需要在项目中添加一个中间件Cors,'POST,GET,OPTIONS,PUT,DELETE','Access-Control-Allow-Headers'=>'Content-Type,X-Auth-Token,Origin'];$response=$next($request);foreach($headersas$key=>$value)$response->header($key,$value);返回$响应;}}对于简单的请求,例如get请求,将其添加到Middleware将执行的路由中。但是对于复杂的请求,是无法处理的。(根据文档,满足一定条件的POST请求是复杂请求,但是不知道为什么,我发的POST请求都是复杂请求,就是浏览器会先触发options请求,然后提交客户的实际要求)。对于简单请求只采用相同的方法,无法正确响应复杂请求。下面是GET请求的请求-响应信息:下面是POST请求的响应:可以看出,在POST请求中,浏览器首先进行了OPTIONS请求,但是在请求的响应中,有GET响应中没有Access-Control-Allow-Headers:Content-Type,X-Auth-Token,OriginAccess-Control-Allow-Methods:POST,GET,OPTIONS,PUT,DELETEAccess-Control-Allow-Origin:*和其他跨域控制字段。通过查询数据,Laravel将自动以200响应OPTIONS请求。因此缺少必要的标头信息。所以,我添加了一个路由来处理路由中的选项Route::options('cors/test',function(){returnresponse('ok')->header('Access-Control-Allow-Methods','POST,GET,OPTIONS,PUT,DELETE')->header('Access-Control-Allow-Headers','Content-Type,X-Auth-Token,Origin');})->middleware('cors');也就是说,它确保OPTIONS响应必要的标头信息。但是该方法需要关闭Laravel中对应路由的CSRF功能。具体来说,在AppHttpMiddlewareVerifyCsrfToken中添加protected$except=['cors/*'];问题虽然解决了,但是很多细节还不清楚,需要进一步研究。
