无法在Web Api 2中获取有效令牌,即使在启用Cors之后也是如此

时间:2016-03-31 18:07:05

标签: asp.net-web-api asp.net-web-api2

所以我在我的VS2015解决方案中安装了NuGet包Microsoft.AspNet.WebApi.Cors.5.2.3,并在我的Web Api项目中启用了CORS。

我已成功使用Fidder测试我的/token POST请求,以及我对API控制器\api\values的GET请求。

如果我使用我在Fiddler中收到的令牌,并将其硬编码到我的JavaScript GET请求中 - 我确实可以从我的单页应用程序向\api\values成功请求。

问题:我无法在本地开发环境中向http://localhost:17883/token发出成功的POST请求。

Chrome中的错误是:

XMLHttpRequest cannot load http://localhost:17883//token.
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
XHR failed loading: POST "http://localhost:17883//token".

我在WebApiConfig.cs中启用了CORS -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
using Newtonsoft.Json.Serialization;

namespace API
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

            // Web API routes
            config.MapHttpAttributeRoutes();

            // *** ENABLE CORS ***
            var cors = new System.Web.Http.Cors.EnableCorsAttribute("*", "*", "*");
            config.EnableCors(cors);
            
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

在我的Angular authService中,我编写了一个API测试函数,该函数连接到我的Login页面上的按钮(此请求成功):

var _apitest = function ()
    {
        var deferred = $q.defer();

        var tkn='cbJZpiF-rEdi_WgWzuFOAxPZ0lBiqivEnOmpSYMPu_fuvu37cpLFzHhzc119GfwIc6dnDivYhhH2a1O2bMa6EExRGa3lvPfzZJHiDDaH6klIU2NFEG5FMxFl_-Z_jBQvPkPyW_31iP6P_oVNZZpXzkQfkwA4zilzKLE7If2Dko6MNNID1lscVfkZ4emJXWpalSXCS4A7qmO-ceIchMfrcbZHgVqBjZC_YHz-DxAfg2lTksUdn8NBir_cDOH5Ymsrzj_bKP1H6WJULDfZEPuh0PpB2DlJEXOV63KWUf7Eubp_FYfni5czD1Z-lh2a2RPRfpRxlMQVBUCCp03_Ul5a6lzOFHSJCJlynidw2DV_InK-oFZEuvQK2Xiy_7wq0JVmx-Nej1bQRN7b2eWK25jjdrTfCNyMdtmDZ7qOSmX3dWuyQhCbp_15ciFhmr7wfIYPzsFssbg-XHtDi2lw87KkJ0IhNmtnsoNyKCrM5ibJG5O5t_gxr3l52JN54Jj2mbeY';

        var req={
            "method": "GET",            
            "url": "http://localhost:17883/api/values",
            "headers": {                
                "Authorization": "Bearer " + tkn
            }
        };        
        $http(req).then(function (data)
        {
            deferred.resolve(data);
        });

        return deferred.promise;
    };

\token的POST请求未成功:

var _loginUserPost = function (loginData)
    {        
        var controllerpath = "/token";    
        var url = serviceBase + controllerpath;
        var body = "username=" + loginData.userName + "&password=" + loginData.password + "&grant_type=password";
        
        var deferred = $q.defer();
        deferred.notify("Logging in user...");

        // POST REQUEST !!
        var req = {
            method: 'POST',
            encoding: 'JSON',
            headers: {
                'Content-Type': 'application;x-www-form-urlencoded'                
            },
            url: url,
            data: body 
        };

        $http(req).then(function (data)
        {
            deferred.resolve(data);
        }, function (err)
        {
            deferred.reject("Failed to login user via api call.");
            console.log("Failed to login user via api call. Errors details: " + err);
        });

        return deferred.promise;
    }

我还尝试使用ApplicationOAuthProvide属性修饰EnableCors类,但它仍然不起作用:

[EnableCors(origins: "*", headers: "*", methods: "*")]
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
     ...
}

我真的需要知道我错过了什么。我一直在寻找和尝试不同的东西 - 但无济于事。

建议表示赞赏。

鲍勃

*********更新 - 到目前为止我尝试了什么************

但是,\token的请求在Chrome中以CORS例外被踢回。

我尝试添加Headers失败(在本文中搜索“第10步:”http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/):

   public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });   // BM:

    ...
   }

1 个答案:

答案 0 :(得分:1)

确保控制器中有Options()Action。它可能在帖子之前发出预检选项请求而没有找到匹配的动作。

public HttpResponseMessage Options()
{
    return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}

根据IIS的配置方式,您可能还需要在web.config中允许选项请求

<system.webServer>
    <security>
      <requestFiltering>
        <verbs applyToWebDAV="false">
          <add verb="OPTIONS" allowed="true" />         
        </verbs>
      </requestFiltering>
    </security>
<system.webServer>

另外,请确保您在Angular中指定的内容类型与Web Api所期望的内容类型相同

var req = {
    // ...
    headers: 
        'Content-Type': 'application;x-www-form-urlencoded'                
    },
    // ..
};