用于PUT和POST的Angular4 ASP.NET Core 1.2 Windows身份验证CORS提供401

xyn*_*cat 8 .net iis asp.net-core-webapi angular

我的IDE是Visual Studio 2017.我有一个Angular4客户端与Core中的WebAPI后端通信,而CORS正在为PUT和POST方法配置EXCEPT.GET方法在Chrome中使用与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');
    }
Run Code Online (Sandbox Code Playgroud)

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();
            });
        });
Run Code Online (Sandbox Code Playgroud)

Startup.cs ConfigureServices

app.UseCors("AllowAll");
Run Code Online (Sandbox Code Playgroud)

Project中的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>
Run Code Online (Sandbox Code Playgroud)

<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>
Run Code Online (Sandbox Code Playgroud)

对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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

所以最重要的问题是,我错过了什么?

Bur*_*ppo 8

这是对我有用的...

首先,添加一个CORS政策,ConfigureServices()Startup.cs

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

并在Configure()方法中使用

app.UseCors("CORSPolicy");
Run Code Online (Sandbox Code Playgroud)

接下来,将Authorize属性添加到控制器或全局添加它们。我去了全球。为此,请在services.AddCors()方法中的上述ConfigureServices()方法之后添加以下内容(您也可以在该谓词中包含其他内容)

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

然后,我添加了这个小块(这就是使一切对我而言都“正常工作”的原因)。基本上,它允许预检请求通过IIS而不进行身份验证。

services.AddAuthentication(IISDefaults.AuthenticationScheme);
Run Code Online (Sandbox Code Playgroud)

我认为您也必须在usings中添加以下内容

using Microsoft.AspNetCore.Server.IISIntegration;
Run Code Online (Sandbox Code Playgroud)

您还应该告诉应用使用身份验证。请按照以下Configure()方法进行操作app.UseCors("CORSPolicy")

app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)

最后,确保你有anonymousAuthenticationwindowsAuthentication设置true您的applicationhost.config文件。如果您不知道该文件是什么,它将为应用程序配置IIS设置。您可以在文件夹中项目根目录的隐藏 .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>
Run Code Online (Sandbox Code Playgroud)

我不知道每个人是否都是这种情况,但是我的文件中有两个 <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();
    }
Run Code Online (Sandbox Code Playgroud)

步骤2)中的,applicationhost.config 您可能必须在文件的两个位置执行此操作

<authentication>
      <anonymousAuthentication enabled="true" />
      <windowsAuthentication enabled="true" />
    </authentication>
Run Code Online (Sandbox Code Playgroud)


xyn*_*cat 5

知道了。好的,基本上,发生的事情是预检 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');
}
Run Code Online (Sandbox Code Playgroud)

启动文件

添加了 CORS,添加了身份验证策略,使用了 CORS。

(在配置服务下)

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

services.AddAuthorization(options =>
        {
            options.AddPolicy("AllUsers", policy => policy.RequireAuthenticatedUser());
        });
Run Code Online (Sandbox Code Playgroud)

(在配置下)

app.UseCors("AllowSpecificOrigin");
Run Code Online (Sandbox Code Playgroud)

控制器

添加了引用启动中创建的策略的授权。

[Authorize(Policy = "AllUsers")]
    [Route("api/[controller]")]    
    public class TagsController : ITagsController
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

我完全删除了自定义标题。

该解决方案允许所有 4 个动词按预期工作,并且我能够使用 httpContext.User 对象中的标识信息将信息记录到数据库中。

将其部署到 IIS 后,我预计必须将 forwardWindowsAuthToken 添加到 web.config:

<aspNetCore processPath=".\TRWD.HydroMart.App.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true" />
Run Code Online (Sandbox Code Playgroud)

这是在 ConfigureServices 中启动的:

services.Configure<IISOptions>(options => {
        options.ForwardWindowsAuthentication = true;
    });
Run Code Online (Sandbox Code Playgroud)


jmj*_*rri 5

我用非常简单的方法让它工作。我使用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();
Run Code Online (Sandbox Code Playgroud)

然后,同时启用 - 匿名身份验证和 Windows 身份验证。这允许始终匿名的 OPTIONS 请求(预检)通过。所有 xhr 请求都必须是 withCredentials 否则将失败。