简而言之,我将Angular的数据发布到Laravel后端 . OPTIONS /预检请求看起来不错,但后续的POST失败,说请求的资源中缺少Access-Control-Allow-Origin标头 .
我正在使用Laravel 5和Angular 1.2.26 . 关于后端中间件的一些进一步文档可以在这里找到:https://laracasts.com/discuss/channels/requests/laravel-5-cors-headers-with-filters .
Laravel中间件:
public function handle($request, Closure $next)
{
return $next($request)->header('Access-Control-Allow-Origin' , 'http://laravel.app:8001')
->header('Access-Control-Allow-Credentials', 'true')
->header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE')
->header('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With')
->header('Access-Control-Max-Age', '28800');
}
Angular配置 - 我尝试了注释代码的各种组合,每次都有相同的结果:
$httpProvider.defaults.useXDomain = true;
//$httpProvider.defaults.withCredentials = true;
//delete $httpProvider.defaults.headers.common["X-Requested-With"];
//$httpProvider.defaults.headers.common["Accept"] = "application/json";
//$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
预检/选项:
Remote Address:127.0.0.1:8000
Request URL:http://laravel.app:8000/api/v1/authentication/login
Request Method:OPTIONS
Status Code:200 OK
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:laravel.app:8000
Origin:http://laravel.app:8001
Referer:http://laravel.app:8001/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Response Headers
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, Accept, Authorization, X-Requested-With
Access-Control-Allow-Methods:POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin:http://laravel.app:8001
Access-Control-Max-Age:28800
Allow:GET,HEAD,POST
Cache-Control:no-cache
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html; charset=UTF-8
Date:Mon, 24 Nov 2014 16:01:57 GMT
Server:nginx/1.6.2
Set-Cookie:laravel_session=blahblah; expires=Mon, 24-Nov-2014 18:01:57 GMT; Max-Age=7200; path=/; httponly
Set-Cookie:XSRF-TOKEN=blahblah; expires=Thu, 01-Jan-1970 00:02:00 GMT; Max-Age=-1416844797; path=/; httponly
Transfer-Encoding:chunked
POST:
Remote Address:127.0.0.1:8000
Request URL:http://laravel.app:8000/api/v1/authentication/login
Request Method:POST
Status Code:500 Internal Server Error
Request Headers
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:47
Content-Type:application/json;charset=UTF-8
Host:laravel.app:8000
Origin:http://laravel.app:8001
Referer:http://laravel.app:8001/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
Request Payload
{email: "x", password: "x", rememberMe: false}
email: "x"
password: "x"
rememberMe: false
Response Headers
Cache-Control:no-cache
Connection:keep-alive
Content-Type:text/html; charset=UTF-8
Date:Mon, 24 Nov 2014 16:01:57 GMT
Server:nginx/1.6.2
Transfer-Encoding:chunked
4 回答
在单步执行VerifyCsrfToken中间件后,我确定它确实是令牌不匹配 .
原因是Angular没有通过标头或帖子中的参数提供CSRF令牌 . 它适用于GET和OPTIONS请求,因为它们不会对令牌进行验证 .
所以,我查看了Angular并且有关于XSRF保护的文档(请参阅https://docs.angularjs.org/api/ng/service/ $ http)以及有关如何添加适当标头(例如https://github.com/angular/angular.js/issues/5122#issuecomment-36157820)的大量讨论 .
我没有机会遵循这一切,因为我必须保持我的项目移动,我的特定用例允许我放弃禁用VerifyCsrfToken,因为我在开发过程中只需要CORS .
但希望这会给别人一个解决这个问题的起点 .
我不确定这是否是Laravel和VerifyCsrfToken中间件的问题,但我的问题的根本原因是CSRF令牌验证失败 . 抛出错误时,不包括新标头 . 我不清楚这些中间件运行的顺序,也许就是这样,但是,一旦我从中间件堆栈中删除了VerifyCsrfToken,一切都亮了起来 .
我有问题 . 如果您使用中间件来设置Headers,但在控制器上创建一个新的Response,
Response::json()
,Response::make()
等,则此新对象不会获得由中间件设置的标头 .我有同样的问题 . 在CORS中间件中添加以下标头 .