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

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

问题描述

我的 IDE 是 Visual Studio 2017.我有一个 Angular4 客户端与 Core 中的 WebAPI 后端通信,并且 CORS 按照配置工作,除了 PUT 和 POST 方法.在 Chrome 中,GET 方法与 PUT 和 POST 方法相同,但 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.

Visual Studio 中的 IIS Express 服务器似乎没有将请求转发到 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 配置服务

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?

推荐答案

明白了.好的,基本上,发生的事情是预检选项请求没有授权,所以默认情况下和设计失败,因为我禁用了匿名身份验证并启用了 Windows 身份验证.我必须允许对客户端和 Web api 进行匿名身份验证,以便 OPTIONS 请求可以毫发无损地通过.然而,这留下了我必须解决的巨大安全漏洞.因为我已经打开了 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.

(在配置服务下)

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

控制器

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

Added authorization referencing the policy created in the Startup.

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

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

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=".logsstdout" 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天全站免登陆