为Angular 2身份验证启用WebAPI CORS

时间:2016-09-12 14:31:58

标签: asp.net-web-api angular typescript cors

我在stackoverflow上看到了一些答案,我迷路了。

我有webapi 2 +独立角2 webapi项目来自模板。我唯一改变的是我添加了CORS 以及与IdentityConfig.cs相关的行> ApplicationUserManager Create()

context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "http://localhost:3000" });

这里我是模板的所有标准:

[Authorize]
public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
            return new string[] { "value1", "value2" };
    }

在客户端,我有获取访问令牌的功能,该功能正常运行:

authenticate(loginInfo: Login): boolean {

        let headers = new Headers(); 
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        this.http.post(this.baseUrl + 'Token', 'grant_type=password&username=alice2@example.com&password=Password2!',
            {
                headers: headers
            })
            .subscribe(
                data => this.saveAuthToken(<AccessToken>(data.json())),
                err => this.handleError(err),
                () => console.log('authentication Complete')
        );           

        return true;        
    }

获取功能,无需身份验证即可正常工作(注释代码):

get(url: string) {         

    var jwt = sessionStorage.getItem(this.idTokenName);
    var authHeader = new Headers();       
    if (jwt) {
        authHeader.append('Authorization', 'Bearer ' + jwt);
    }        

    return this.http.get(this.apiUrl + url, {
            headers: authHeader
        })
        .map(res => res.json())
        .catch(this.handleError);       

    //return this.http.get(this.apiUrl + url)
    //    .map(res => res.json())
    //    .catch(this.handleError);   
}  

但是当我尝试添加Authorization标头服务器时返回:

XMLHttpRequest cannot load http://localhost:3868/api/values. Response for preflight has invalid HTTP status code 405

如何让用户正确通过Angular进行身份验证?

4 个答案:

答案 0 :(得分:5)

  1. 安装包Microsoft.Owin.Cors
  2. 添加到App_Start&gt; Startup.Auth.cs&gt; ConfigureAuth(IAppBuilder应用程序)

       app.UseCors(CorsOptions.AllowAll);
    
  3. 只有一行。就是这样。

答案 1 :(得分:0)

您可以明确添加所需的标题和方法:

context.Response.Headers.Add(
    "Access-Control-Allow-Headers", 
    new[] { "Content-Type, Authorization" }
);

context.Response.Headers.Add(
    "Access-Control-Allow-Methods", 
    new[] { "GET, POST, OPTIONS" }
);

答案 2 :(得分:0)

我必须将以下内容添加到globalasax.cs:

protected void Application_BeginRequest()
{
   var req = HttpContext.Current.Request;
   var res = HttpContext.Current.Response;

   var val = res.Headers.GetValues("Access-Control-Allow-Origin");
   if (val == null)
   {
      if (!req.Url.ToString().ToLower().Contains("token") || (req.Url.ToString().ToLower().Contains("token") && req.HttpMethod == "OPTIONS"))
      {
      res.AppendHeader("Access-Control-Allow-Origin", "http://localhost:4200");
      }
   }

   if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
   {
      res.AppendHeader("Access-Control-Allow-Credentials", "true");
      res.AppendHeader("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
      res.AppendHeader("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");

      res.StatusCode = 200;
      res.End();
   }
}

答案 3 :(得分:0)

当谈到webapi angular并使用包含非标准正文内容(即json)或身份验证的http帖子时,会设置一个基本上说“我可以发送实际请求”的飞行前请求。现在有几种解决方法,主要涉及捷径 - 使用IE(如果服务器与IE在同一台机器上,在决定同一台机器时忽略端口)或打开CORS以允许所有(这是危险的,因为向经过身份验证的用户授予权限可以使系统打开各种黑客攻击。)

无论如何,我们使用的解决方案是向服务器上的Globals.asax.cs添加一个方法

protected void Application_BeginRequest()
    {
        if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
        {
            var origin = HttpContext.Current.Request.Headers["Origin"];

            Response.Headers.Add("Access-Control-Allow-Origin", origin);
            Response.Headers.Add("Access-Control-Allow-Headers", "content-type, withcredentials, Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
            Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            Response.Headers.Add("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT, DELETE");

            Response.Flush();
        }
    }

现在上面是非常具体地检查飞行前,如果发现它,它会添加发送下一个请求的权限。在您的系统上,您可能需要调整Allow_Headers请求(最简单的方法是使用浏览器f12查看您的飞行前请求实际发送的标头。

请注意,以上只是处理飞行前的CORS仍然适用于需要正确处理的实际http POST。为此我们将我们想要允许的服务器添加到设置中,然后将System.Web.Http.Cors添加到WebApiConfig Register方法,如下所示

var cors = new EnableCorsAttribute(Properties.Settings.Default.CORSOriginPermittedSite, "*", "GET, HEAD, OPTIONS, POST, PUT, DELETE");
        cors.SupportsCredentials = true;
        config.EnableCors(cors);

这避免了对生产系统真正想要避免的网站进行硬编码。

无论如何,希望这会有所帮助。