簡體   English   中英

用於 PUT 和 POST 的 Angular4 ASP.NET Core 1.2 Windows 身份驗證 CORS 給出 401

[英]Angular4 ASP.NET Core 1.2 Windows Authentication CORS for PUT and POST Gives 401

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

Visual Studio 中的 IIS Express 服務器似乎沒有將請求轉發到 Kestrel 服務器。 這兩種方法在 Postman 中都有效,但在 Angular4 調用時無效。 這是代碼:

Angular4 POST

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

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

這是對我有用的...

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

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

並在Configure()方法中使用

app.UseCors("CORSPolicy");

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

            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;

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

app.UseAuthentication();

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

<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>

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


**

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();
    }

STEP 2) 在applicationhost.config您可能必須在文件中的兩個地方執行此操作

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

知道了。 好的,基本上,發生的事情是預檢 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');
}

啟動文件

添加了 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;
    });

我用非常簡單的方法讓它工作。 我使用dotNet Core 2.0

In configureServices method of startup

services.AddCors(options =>
        {
            options.AddPolicy("app-cors-policy",
                builder =>
                {
                    builder
                        .AllowAnyOrigin()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials()
                    ;
                });

        });


In configure method of startup

app
   .UseCors("app-cors-policy") //Must precede UseMvc
   .UseMvc();

然后,同時啟用 - 匿名身份驗證和 Windows 身份驗證。 這允許始終匿名的 OPTIONS 請求(預檢)通過。 所有 xhr 請求都必須是 withCredentials 否則將失敗。

要允許匿名預檢選項,您可以將以下內容添加到您的 web.config

<security>
   <authorization>
       <remove users="*" roles="" verbs="" />
       <add accessType="Allow" users="" roles="mydomain/mygroup" />
       <add accessType="Allow" users="?" verbs="OPTIONS" />
   </authorization>
</security>

注意:使用組來限制經過身份驗證的用戶的訪問並將匿名用戶的訪問限制為 OPTIONS 動詞。

如果您還沒有,請添加 cors 包Microsoft.AspNetCore.Cors

並配置它。

可以在此處找到配置 CORS 的良好指南:

現在有這個: https : //www.iis.net/downloads/microsoft/iis-cors-module

“Microsoft IIS CORS 模塊是一個擴展,它使網站能夠支持 CORS(跨源資源共享)協議。”

伍迪杜

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM