CORS preflight OPTIONS 请求从 Windows Authenticated web api 返回 401(未授权)

Posted

技术标签:

【中文标题】CORS preflight OPTIONS 请求从 Windows Authenticated web api 返回 401(未授权)【英文标题】:CORS preflight OPTIONS request returns 401 (Unauthorized) from Windows Authenticated web api 【发布时间】:2019-01-05 01:45:06 【问题描述】:

我有一个使用Windows Authentication.NET Web API 项目。在我的开发环境中,我无法使用来自我的 Angular 应用程序的数据成功执行 POST 请求。它返回:

OPTIONS http://localhost:9090/api/values 401 (Unauthorized)
Failed to load http://localhost:9090/api/values: Response for preflight has invalid HTTP status code 401.

我尝试了所有使用 Microsoft.AspNet.WebApi.Cors 实现 cors 的方法,但无济于事。但目前我已经从我的项目中删除了Microsoft.AspNet.WebApi.Cors 包,转而使用web.config 方法(如果我实际上仍然需要安装Microsoft.AspNet.WebApi.Cors 来在Web.config 中执行以下操作,请告诉我):

Web.config:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="http://localhost:5200" />
    <add name="Access-Control-Allow-Headers" value="*" />
    <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
    <add name="Access-Control-Allow-Credentials" value="true" />
  </customHeaders>
</httpProtocol>

.NET Web API 'ValuesController.cs':

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace api.Controllers

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

        // GET api/values/5
        public string Get(int id)
        
            return "value";
        

        // POST api/values
        public void Post([FromBody]string value)
        
        

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        
        

        // DELETE api/values/5
        public void Delete(int id)
        
        
    

Angular 组件(向我的 Angular 服务发送数据):

  constructor(private myService: MyService) 
    this.myService.myPost(ID: 1, FirstName: 'Bob')
    .subscribe(
      data => console.warn(data),
      err => console.error(err),
      () => console.log("empty")
    );
  

Angular Service(将组件的数据发布到我的Web API):

import  Injectable  from '@angular/core';
import  HttpClient, HttpResponse, HttpRequest, HttpHeaders, HttpInterceptor, HttpHandler, HttpEvent, HttpParams from '@angular/common/http';

import  Observable  from 'rxjs';
import  from  from 'rxjs';
import  map, filter, catchError, mergeMap  from 'rxjs/operators';

@Injectable(
  providedIn: 'root'
)
export class MyService 

  constructor(private http: HttpClient) 

  ;


  public myPost(body) 

      const httpOptions = 
         withCredentials: true
      

      return this.http.post("http://localhost:9090/api/values", body, httpOptions);

  


从我的研究看来,也许我需要通过服务中的httpOptions 变量在我的请求中传递一个Authorization 标头。但我不知道传递什么作为Authorization 属性的值。请参阅下面的问号: MyService.ts

  public myPost(body) 
    const httpOptions = 
      headers: new HttpHeaders(
        'Authorization': '?????'
      ),
      withCredentials: true
    
      return this.http.post("http://localhost:9090/api/values", body, httpOptions);
  

也许这甚至不是我的问题。 CORS + Windows 身份验证 - 有什么想法吗?

【问题讨论】:

docs.microsoft.com/en-us/iis/extensions/cors-module/… 您必须使用此 IIS 模块来响应预检请求的 CORS 标头。删除上面的所有自定义标题。 【参考方案1】:

您是否允许来自端口 4200 的 CORS 连接,这是使用 Angular CLI 的 Angular 应用程序的默认端口?

您也可以像这样添加标头(前提是您有不记名令牌):

将下面的 GET 更改为 POST。

使用 Http

import  Http, Headers, Response  from '@angular/http';

    const headers = new Headers( 'Authorization': 'Bearer ' + token);
          const options = 
            headers: headers,
            withCredentials: true
          ;

    return this.http.get('http://localhost:9090/api/values', options)
          .map((response: Response) => 
            const stuff = response.json();
            return stuff;
          ).catch(error => Observable.throw(error));

使用 HttpClient

import  HttpClient, HttpHeaders  from '@angular/common/http';

const httpOptions = 
      headers: new HttpHeaders( 'Content-Type': 'application/json' ),
      withCredentials: true
    ;

    this.http
      .post('http://localhost:9090/api/values', body, httpOptions)
      .pipe(        
        catchError(this.handleErrors)        
      ).subscribe((result: any) => 
        return Observable.of(result);
      );

【讨论】:

我已将 CORS 来源配置为 port 5200。我只是在 vsCode 中打开我的 Angular 项目并执行 ng serve --port 5200 并尝试从那里发布。 我明白了。那不是问题。我不确定您是否覆盖了默认端口。【参考方案2】:

添加:

App_Start/WebApiConfig - 注册方法:

config.EnableCors();

如果不起作用,请尝试

FooController:

[EnableCors(origins: "*", headers: "*", methods: "*")]

【讨论】:

以上是关于CORS preflight OPTIONS 请求从 Windows Authenticated web api 返回 401(未授权)的主要内容,如果未能解决你的问题,请参考以下文章

CORS Preflight 请求是不是包含请求的标头?

对 CORS preflight OPTIONS 请求的响应是 Laravel API 中的 500 Internal Server Error

Preflight(options) 请求的正确成功状态代码是啥? [复制]

HTTP协议详解(HyperText Transfer Protocol 超文本传输协议)访问控制(CORS) (OPTIONS预请求preflight request)浏览器同源策略

CORS 中的POST and OPTIONS 请求

已解决 - CORS、OPTIONS 和 PreFlight 问题 在 Vue.js 中使用 Axios 使用 REST API