繁体   English   中英

使用 Windows 身份验证的 Asp.net 核心 Web api - Cors 请求未经授权

[英]Asp.net core web api using windows authentication - Cors request unauthorised

在我的 asp.net core web api 中,我已经按照MS 文档中的文章配置了 Cors。 Web api 应用程序正在使用 Windows 身份验证(未启用匿名身份验证)。 startup.cs创建了Cor的策略并添加了中间件,如下所示

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.WithOrigins("http://localhost:4200")
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
            );
    });

    services.AddMvc().AddJsonOptions(options => {
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{         
    //Enable CORS policy 
    app.UseCors("CorsPolicy");
    app.UseMvc();
}

还应用了每个控制器级别的策略

[EnableCors("CorsPolicy"), Route("api/[controller]")]
public class LocationController : BaseController<Location>
{
  //code
}

选项请求变得未经授权。 请求和响应看起来像

在此处输入图片说明

我见过类似的问题并尝试了几乎所有解决方案,但选项请求仍然失败。

您可能想阅读此线程: https : //github.com/aspnet/CORS/issues/60 您可以混合使用匿名和 NTLM,以便不会拒绝您的 CORS 预检(因为它们不包含 Windows 凭据)。 IIS 在它到达中间件之前处理 NTLM 身份验证,所以这可能是 IIS 的事情。 您可能需要允许匿名 COR 预检。

1) 在launchSettings.json 文件(开发设置文件)中将Allow Windows 和anonymous Authentication 标志设置为true。

匿名身份验证:需要允许飞行前选项请求。

{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": true,
    "iis": 
      ...
}

2) 在配置服务方法中添加 Cors 策略。

public void ConfigureServices(IServiceCollection services)
{
         
        ...
          services.AddCors(options =>
              {
                  options.AddPolicy("MyCustomCorsPolicyName",
                              builder => builder.WithOrigins("http://YourDomainName/")
                                      .AllowAnyMethod()
                                      .AllowAnyHeader()
                                      .AllowCredentials()
                              );
              });
          services.AddAuthentication(IISDefaults.AuthenticationScheme);
          services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);      
}
   

3:将 CORS 中间件添加到您的 Web 应用程序管道以允许跨域请求。

public void Configure(IApplicationBuilder app)
{
   ....
   app.UseCors("MyCustomCorsPolicyName");
   app.UseMvc();
}

4)在控制器顶部添加授权属性以强制,客户端发送凭据

[Authorize]
public class MyAPIController : ControllerBase
{
...
}

5) 在 JQuery 或您使用的任何客户端中,将 withCredentials 属性标志设置为 true

$.ajax({
                type: "POST",
                datatype: "json",  
                url: "YourApiUrl",              
                xhrFields: {
                    withCredentials: true
                }

这在我使用 .net core 2.2、带有 Windows 身份验证的 IIS Express 的开发环境中对我有用。

使用 IIS CORS 模块很好地解决了这个问题。 以下网址供参考。

使用 Windows 身份验证 虽然这绝不是 CORS 模块解决的唯一方案,但它非常重要,值得一提。 以前,如果您尝试向使用 Windows 身份验证的应用程序发出跨域请求,您的预检请求将失败,因为浏览器未随预检请求发送凭据。 如果不在您的应用程序中启用匿名身份验证,则无法解决此问题。 由于 CORS 模块在身份验证之前启动,因此可以在不影响应用程序安全模型的情况下处理飞行前请求。 下面是您的 web.config 可能是什么样子的示例。

https://blogs.iis.net/iisteam/getting-started-with-the-iis-cors-module

示例代码:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- To customize the asp.net core module uncomment and edit the following section. 
         For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
         <system.web>
        <authentication mode="Windows"/>
    </system.web>
  <system.webServer>
  <cors enabled="true" failUnlistedOrigins="true">
            <add origin="http://localhost:60096" allowCredentials="true" >
            <allowHeaders allowAllRequestedHeaders="true">
                    <add header="Header1" />
                </allowHeaders>
            </add>
        </cors>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\Project.Api.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
  </system.webServer>
</configuration>

这与启用 CORS非常相似, 在 POST JSON并为我提供解决方案时,预检响应具有无效的 HTTP 状态代码 404 (我在 POST 请求上出现 401 错误)。 此外,不应同时配置 NTLM 和协商( 协商 V/s NTLM )。

看起来您想要传递凭证或与请求一起传递。

请检查此链接以添加凭据/允许用户凭据。

允许跨域凭据时要小心。 另一个域中的网站可以在用户不知情的情况下代表用户将登录用户的凭据发送到应用程序。 CORS 规范还指出,如果存在 Access-Control-Allow-Credentials 标头,则将来源设置为“*”(所有来源)是无效的。

经过几个小时的研究,这是一个完整的解决方案(前端到后端):

我的问题:当我在我的 Web API 上启用 Windows 身份验证时,我无法从我的 React 应用程序获取调用到我的 .NET Core 3.1 Web API,CORS 吓坏了。 使用匿名身份验证它有效,但在启用 Windows 身份验证时无效。

1.launchSettings.json

这将仅用于您的开发环境,请确保在您的生产服务器上的 IIS 中也启用了 Windows 身份验证。

{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    "iisExpress": {
      "applicationUrl": "http://localhost:58747",
      "sslPort": 0
    }
  },
 {... more settings if any}
}

2.Startup.cs:

此处启用 CORS 策略。 方法的顺序在这里很重要。 此外,您不需要在 web.config 中设置它们

public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", //give it the name you want
                           builder =>
                           {
                               builder.WithOrigins( "http://localhost:3000", //dev site
                                                    "production web site"
                                                   .AllowAnyHeader()
                                                   .AllowAnyMethod()
                                                   .AllowCredentials();
                           });
        });

        //database services here

        services.AddControllers();
    }

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

        app.UseRouting();

        // global policy same name as in the ConfigureServices()
        app.UseCors("CorsPolicy");

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

3.控制器:

using Microsoft.AspNetCore.Cors;
... your other usings

namespace ProjectTest.Controllers
{
    [ApiController]
    [EnableCors("CorsPolicy")] //THIS HERE needs to be the same name as set in your startup.cs
    [Route("[controller]")]
    public class FooController:Controller
    {
        [HttpGet("getTest")]
        public JsonResult GetTest()
        {
            return Json("bar");
        }
    }
}

4.React 组件获取调用示例:

“凭证:'包含'”是秘密

    await fetch('http://localhost:3000/Foo/getTest', {
        method: 'GET',
        credentials: 'include'
    }).then(resp => resp.json());

只是注意 CORS 中间件在 IIS 中不起作用,请在此处查看此线程

  1. 在 IIS 中安装CORS 模块
  2. 转换您的 web.config(顺便说一句,我使用的是 .net core 3.1)
  3. 在应用的根目录添加web.release.config
  4. 遵循此 XML 代码
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

  <system.web xdt:Transform="Insert">
    <authentication mode="Windows"/>
  </system.web>

  <system.webServer xdt:Transform="Insert">
    <cors enabled="true" failUnlistedOrigins="true" >
      <add origin="your origin" allowCredentials="true" >
        <allowHeaders allowAllRequestedHeaders="true">
          <add header="your header" />
        </allowHeaders>
      </add>
    </cors>
  </system.webServer>

</configuration>
  1. 在 IIS 中部署您的应用程序

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM