使用CORS避免预检OPTIONS请求

时间:2015-05-22 18:52:32

标签: asp.net angularjs http asp.net-web-api cors

我正在构建一个与使用ASP.NET Web API 2构建的API交互的Angular应用程序。我使用基本身份验证,通过为每个需要身份验证的请求发送Authorization标头:

Angular片段:

$http.defaults.headers.common['Authorization'] = authHeader;

请求

Accept:application/json, text/javascript
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Max-Age:1728000
Authorization:Basic [base64 encoded credential couplet here]
Connection:keep-alive
DNT:1
Host: blah.com
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/53

这一切都可行,但每次OPTIONSGET请求都会发送预检POST请求。这主要影响应用程序的感知速度。我已经对CORS“简单请求”进行了大量阅读,似乎为了避免可怕的预检OPTIONS请求,请避免在我的请求中添加任何自定义标头。我尝试了很多其他的东西,例如发送Content-Type text/plain,但似乎Authorization标头违反了CORS“简单请求”要求。

所以我似乎不得不将API移到使用基于令牌的身份验证/授权。为了避免预检请求,似乎我需要将令牌放在查询字符串中。这是可以的,因为它只是一个小的内部网络应用程序,无论如何只能由几个用户访问。我打算在控制器响应上实现缓存。由于每个对控制器操作的请求都会根据当前经过身份验证的用户在查询字符串中使用不同的令牌,这会使缓存无效吗?

所以:

  1. 如何避免预检请求(如果可能的话,使用自定义授权标头)
  2. 如果无法1.),并且我转移到基于令牌的身份验证,我将无法缓存控制器操作的API响应
  3. 哪种方法最常用,可以避免预检请求,还可以安全地授权用户?
  4. nb我知道在网上和其他网站上有关于此的其他几个主题,但是它们都没有提供关于是否有可能避免GET的预检请求的确定答案。使用自定义POST授权标头时HTTP

2 个答案:

答案 0 :(得分:10)

我认为这篇文章(How to apply CORS preflight cache to an entire domain)几乎说明了一切 - 你可以做的很少

一个简单的解决方案是向服务于您的角度应用的代理/网络服务器添加反向代理(例如nginx),以通过同一个域路由您的RESTful呼叫,例如: appdomain.com/api - > apidomain.com。

答案 1 :(得分:2)

另一种似乎对我有效的解决方案。可以直接从nginx返回预检请求,从而将预检请求所需的时间缩短到几毫秒,而不是设置代理并需要路由到同一个域。

这是一个可以与nginx一起使用的简单代码段。

 location / {
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
     }
}

一旦预检请求成功,就可以简单地添加" Access-Control-Allow-Origin"和其他必要的东西,以及' GET' POST'请求等...