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

查看:477
本文介绍了用于PUT和POST的Angular4 ASP.NET Core 1.2 Windows身份验证CORS提供401的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的IDE是Visual Studio 2017.我有一个Angular4客户端与Core中的WebAPI后端通信,而CORS正在为PUT和POST方法配置EXCEPT。 GET方法在Chrome中使用与PUT和POST方法相同的预检OPTIONS方法,但GET工作正常。

My IDE is Visual Studio 2017. I've got an Angular4 client talking to a WebAPI backend in Core, and CORS is working as configured EXCEPT for the PUT and POST methods. The GET method is subject to the same preflight OPTIONS method in Chrome that the PUT and POST methods are, but GET is working fine.

看来IIS Express服务器在Visual Studio不会将请求转发到Kestrel服务器。两种方法都适用于Postman,但不适用于Angular4进行调用的情况。以下是代码:

It appears that the IIS Express server in Visual Studio is not forwarding the requests to the Kestrel server. Both Methods work in Postman, but not when Angular4 makes the call. Here's the code:

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 ConfigureServices

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>

AND

<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

所以最大的问题是,我缺少什么?

So the big question is, what am I missing?

推荐答案

知道了。好吧,基本上,发生的事情是预检OPTIONS请求没有授权,因此默认情况下设计失败,因为我禁用了匿名身份验证并启用了Windows身份验证。我不得不允许客户端和Web api进行匿名身份验证,以便OPTIONS请求可以通过unscathed进行。然而,这留下了我必须解决的巨大安全漏洞。由于我打开了OPTIONS请求的大门,我不得不以某种方式关闭该门以进行POST,PUT和DELETE请求。我通过创建仅允许经过身份验证的用户的授权策略来实现此目的。我的最终代码如下:

Got it. Okay, so basically, what was happening was a preflight OPTIONS request doesn't have authorization on it, so it was by default and design, failing since I had disabled anonymous authentication and enabled windows authentication. I had to allow anonymous authentication to occur to both the client and the web api so that the OPTIONS requests could get through unscathed. This, however, leaves a huge security hole that I had to resolve. Since I had opened the door to the OPTIONS requests, I had to close that door somehow for the POST, PUT and DELETE requests. I did this by creating an authorization policy that only allowed in authenticated users. My final code is as follows:

Angular 4 Post

注意使用选项中的withCredentials。

Note the use of withCredentials in the options.

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

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

Added CORS, added an authentication policy, used CORS.

(在ConfigureServices下)

(under ConfigureServices)

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");

控制器

添加了引用在Startup中创建的策略的授权。

Added authorization referencing the policy created in the Startup.

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

IISExpress的 applicationhost.config

applicationhost.config for IISExpress

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

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

I totally removed the custom headers.

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

This solution allowed all 4 verbs to work as expected and I was able to use the identifying information in the httpContext.User object to log information to the database.

一旦我将此部署到IIS,我希望必须将forwardWindowsAuthToken添加到web.config:

Once I deploy this to IIS, I expect will have to add the forwardWindowsAuthToken to the web.config:

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

这与ConfigureServices中的启动:

this to the startup in ConfigureServices:

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

这篇关于用于PUT和POST的Angular4 ASP.NET Core 1.2 Windows身份验证CORS提供401的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆