Dot-Net

Angular4 ASP.NET Core 1.2 Windows Authentication CORS for PUT 和 POST 給出 401

  • April 24, 2020

我的 IDE 是 Visual Studio 2017。我有一個 Angular4 客戶端與 Core 中的 WebAPI 後端通信,並且除了 PUT 和 POST 方法之外,CORS 正在按照配置的方式工作。GET 方法受制於 Chrome 中與 PUT 和 POST 方法相同的預檢 OPTIONS 方法,但 GET 工作正常。

Visual Studio 中的 IIS Express 伺服器似乎沒有將請求轉發到 Kestrel 伺服器。這兩種方法都可以在 Postman 中使用,但在 Angular4 進行呼叫時不起作用。這是程式碼:

Angular4 發布

post(api: string, object: any): Observable<any> {
       let body = JSON.stringify(object);

       let options = new RequestOptions({
           headers: this.headers,
           withCredentials: true
           });

       return this.http.post(this.server + api, body, options)
           .map((res: Response) => res.json())
           .catch((error: any) => Observable.throw(error.json().error) || 'Post server error');
   }

Startup.cs 配置

services.Configure<IISOptions>(options => 
    options.ForwardWindowsAuthentication = true);

services.AddCors(options => {
           options.AddPolicy("AllowAll", builder => {
               builder.WithOrigins("http://localhost:XXXX")
               .WithMethods("GE‌​T", "POST", "PUT", "DELETE", "OPTIONS")
               .WithHeaders("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization")
               .AllowCredentials();
           });
       });

Startup.cs 配置服務

app.UseCors("AllowAll");

項目中的 IIS ApplicationHost.Config

<anonymousAuthentication enabled="false" userName="" />
   <basicAuthentication enabled="false" />
   <clientCertificateMappingAuthentication enabled="false" />
   <digestAuthentication enabled="false" />
   <iisClientCertificateMappingAuthentication enabled="false"></iisClientCertificateMappingAuthentication>
   <windowsAuthentication enabled="true" >
     <providers>
       <add value="Negotiate" />
     </providers>
   </windowsAuthentication>

<customHeaders>
   <clear />
   <add name="X-Powered-By" value="ASP.NET" />
   <add name="Access-Control-Allow-Origin" value="http://localhost:5000"/>
   <add name="Access-Control-Allow-Headers" value="Accept, Origin, Content-
       Type"/>
   <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, 
       OPTIONS"/>
   <add name="Access-Control-Allow-Credentials" value="true"/>
</customHeaders>

對 GET 的響應

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: **Kestrel**
X-SourceFiles: =?UTF-8?B?QzpcZGV2cHJvamVjdHNcVFJXRC5IeWRyb21hcnRBZG1pblxKVF9BZGRUYWdNYW5hZ2VtZW50XFRSV0QuSHlkcm9NYXJ0LkFwcFxhcGlcdGFncw==?=
Persistent-Auth: true
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: http://localhost:5000
Access-Control-Allow-Headers: Accept, Origin, Content-Type
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 14 Jul 2017 17:03:43 GMT

對 POST 的響應

HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-SourceFiles: =?UTF-8?B?QzpcZGV2cHJvamVjdHNcVFJXRC5IeWRyb21hcnRBZG1pblxKVF9BZGRUYWdNYW5hZ2VtZW50XFRSV0QuSHlkcm9NYXJ0LkFwcFxhcGlcdGFncw==?=
WWW-Authenticate: Negotiate
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: http://localhost:5000
Access-Control-Allow-Headers: Accept, Origin, Content-Type
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 14 Jul 2017 17:05:11 GMT
Content-Length: 6095

所以最大的問題是,我錯過了什麼?

知道了。好的,基本上,發生的事情是預檢 OPTIONS 請求沒有授權,所以它是預設和設計的,因為我禁用了匿名身份驗證並啟用了 Windows 身份驗證,所以它失敗了。我必須允許客戶端和 Web api 都進行匿名身份驗證,以便 OPTIONS 請求可以毫髮無損地通過。然而,這留下了一個我必須解決的巨大安全漏洞。由於我已經打開了 OPTIONS 請求的大門,我不得不以某種方式關閉 POST、PUT 和 DELETE 請求的大門。我通過創建僅允許經過身份驗證的使用者的授權策略來做到這一點。我的最終程式碼如下:

角 4 柱

注意選項中 withCredentials 的使用。

post(api: string, object: any): Observable<any> {
   let body = JSON.stringify(object);

   let options = new RequestOptions({
       headers: this.headers,
       withCredentials: true
       });

   return this.http.post(this.server + api, body, options)
       .map((res: Response) => res.json())
       .catch((error: any) => Observable.throw(error.json().error) || 'Post server error');
}

啟動.cs

添加了 CORS,添加了身份驗證策略,使用了 CORS。

(在配置服務下)

services.AddCors(options =>
       {
           options.AddPolicy("AllowSpecificOrigin",
               builder => builder.WithOrigins("http://localhost:5000")
               .AllowAnyMethod()
               .AllowAnyHeader()
               .AllowCredentials());
       });

services.AddAuthorization(options =>
       {
           options.AddPolicy("AllUsers", policy => policy.RequireAuthenticatedUser());
       });

(在配置下)

app.UseCors("AllowSpecificOrigin");

控制器

添加了引用在啟動中創建的策略的授權。

[Authorize(Policy = "AllUsers")]
   [Route("api/[controller]")]    
   public class TagsController : ITagsController

IISExpress 的 applicationhost.config

<authentication>
       <anonymousAuthentication enabled="false" userName="" />
       <basicAuthentication enabled="false" />
       <clientCertificateMappingAuthentication enabled="false" />
       <digestAuthentication enabled="false" />
       <iisClientCertificateMappingAuthentication enabled="false"></iisClientCertificateMappingAuthentication>
       <windowsAuthentication enabled="true">
         <providers>
           <add value="Negotiate" />
           <add value="NTLM" />
         </providers>
       </windowsAuthentication>
     </authentication>

我完全刪除了自定義標題。

該解決方案允許所有 4 個動詞按預期工作,並且我能夠使用 httpContext.User 對像中的辨識資訊將資訊記錄到數據庫中。

一旦我將它部署到 IIS,我希望必須將 forwardWindowsAuthToken 添加到 web.config:

<aspNetCore processPath=".\TRWD.HydroMart.App.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true" />

這到 ConfigureServices 中的啟動:

services.Configure<IISOptions>(options => {
       options.ForwardWindowsAuthentication = true;
   });

這對我有用…

首先,將 CORS 策略添加ConfigureServices()Startup.cs

services.AddCors(o => o.AddPolicy("CORSPolicy", builder =>
       {
           builder.AllowAnyOrigin()
                  .AllowAnyMethod()
                  .AllowAnyHeader()
                  .AllowCredentials();
       }));

並在Configure()方法中使用

app.UseCors("CORSPolicy");

接下來,將Authorize屬性添加到您的控制器或全域添加它們。我去了全球。為此,請在services.AddCors()方法中的上述ConfigureServices()方法之後添加以下內容(您也可以在該謂詞中包含其他內容)

           services.AddMvc(options =>
       {
           var policy = new AuthorizationPolicyBuilder()
                            .RequireAuthenticatedUser()
                            .Build();
           options.Filters.Add(new AuthorizeFilter(policy));
       }); 

然後,我添加了這個小塊(這就是讓一切對我來說“正常工作”的原因)。基本上,它允許預檢請求通過 IIS 而無需進行身份驗證。

services.AddAuthentication(IISDefaults.AuthenticationScheme);

我認為您也必須將以下內容添加到您using的 s 中

using Microsoft.AspNetCore.Server.IISIntegration;

您還應該告訴應用程序使用身份驗證。Configure()在下面的方法中執行此操作app.UseCors("CORSPolicy")

app.UseAuthentication();

最後,確保您的文件中有anonymousAuthenticationwindowsAuthentication設置為。如果您不知道該文件是什麼,它會配置應用程序的 IIS 設置。您可以在文件夾內項目根目錄的隱藏文件夾中找到它。true``applicationhost.config .vs``config

<authentication>
   <anonymousAuthentication enabled="true" userName="" />
   <basicAuthentication enabled="false" />
   <clientCertificateMappingAuthentication enabled="false" />
   <digestAuthentication enabled="false" />
   <iisClientCertificateMappingAuthentication enabled="false"></iisClientCertificateMappingAuthentication>
   <windowsAuthentication enabled="true">
     <providers>
       <add value="Negotiate" />
       <add value="NTLM" />
     </providers>
   </windowsAuthentication>
 </authentication>

我不知道每個人是否都是這種情況,但我的文件中有兩個 <authentication></authentication>部分applicationhost.config。為了安全起見,我將兩者都更改了,並且沒有嘗試更改其中一個而不是另一個。


**

TLDR;

**

第1步)

public void ConfigureServices(IServiceCollection services)
   {
       services.AddCors(o => o.AddPolicy("CORSPolicy", builder =>
       {
           builder.AllowAnyOrigin()
                  .AllowAnyMethod()
                  .AllowAnyHeader()
                  .AllowCredentials();
       }));

       services.AddAuthentication(IISDefaults.AuthenticationScheme);

       services.AddMvc(options =>
       {
           var policy = new AuthorizationPolicyBuilder()
                            .RequireAuthenticatedUser()
                            .Build();
           options.Filters.Add(new AuthorizeFilter(policy));
       }); 
   }

   public void Configure(IApplicationBuilder app, IHostingEnvironment env)
   {
       if (env.IsDevelopment())
       {
           app.UseDeveloperExceptionPage();
       }

       app.UseCors("CORSPolicy");

       app.UseAuthentication();

       app.UseMvc();
   }

第 2 步)在applicationhost.config 您可能需要在文件中的兩個位置執行此操作

<authentication>
     <anonymousAuthentication enabled="true" />
     <windowsAuthentication enabled="true" />
   </authentication>

引用自:https://stackoverflow.com/questions/45108307