Asp.net 核心网站 api 使用 windows 身份验证 - Cors 请求未经授权
Asp.net core web api using windows authentication - Cors request unauthorised
在我的 asp.net 核心网站 api 中,我已经按照 MS documentation 中的文章配置了 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 预检。
这与 and provided solution working for me(I had 401 error on POST requests). Also NTLM and Negotiate should not be configured both(Negotiate V/s NTLM) 非常相似。
您似乎想要传递凭据或随请求一起传递。
请检查 this link 添加凭据/允许用户凭据。
允许 cross-origin 凭据时要小心。另一个域中的网站可以在用户不知情的情况下代表用户将 logged-in 用户的凭据发送到应用程序。 CORS 规范还指出,如果存在 Access-Control-Allow-Credentials header,则将原点设置为“*”(所有原点)无效。
使用 IIS CORS 模块很好地解决了这个问题。以下URL供参考
使用 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>
经过几个小时的研究,这是一个完整的解决方案(前端到后端):
我的问题:当我在我的网络 API 上启用 windows 身份验证时,我无法从我的 React 应用程序获取调用到我的 .NET Core 3.1 网络 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.Controller(s):
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 组件获取调用示例:
"credential: 'include'"是秘密
await fetch('http://localhost:3000/Foo/getTest', {
method: 'GET',
credentials: 'include'
}).then(resp => resp.json());
1) 在 launchSettings.json 文件(开发设置文件)中将允许 Windows 和匿名身份验证标志设置为 true。
匿名身份验证:需要允许飞行前选项请求。
{
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iis":
...
}
2) 在Configure service方法中添加Cors Policy
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 的开发环境中对我有用,IIS Express 具有 Windows 身份验证。
请注意,CORS 中间件在 IIS 中不起作用,请参阅此帖子 here
- 安装CORS module in IIS
- 改造你的 web.config(顺便说一句,我使用的是 .net core 3.1)
- 在您的应用的根目录中添加
web.release.config
- 遵循此 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>
- 在 IIS 中部署您的应用程序
在我的 asp.net 核心网站 api 中,我已经按照 MS documentation 中的文章配置了 Cors。 Web api 应用程序正在使用 windows 身份验证(未启用匿名身份验证)。在 startup.cs
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 预检。
这与 and provided solution working for me(I had 401 error on POST requests). Also NTLM and Negotiate should not be configured both(Negotiate V/s NTLM) 非常相似。
您似乎想要传递凭据或随请求一起传递。
请检查 this link 添加凭据/允许用户凭据。
允许 cross-origin 凭据时要小心。另一个域中的网站可以在用户不知情的情况下代表用户将 logged-in 用户的凭据发送到应用程序。 CORS 规范还指出,如果存在 Access-Control-Allow-Credentials header,则将原点设置为“*”(所有原点)无效。
使用 IIS CORS 模块很好地解决了这个问题。以下URL供参考
使用 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>
经过几个小时的研究,这是一个完整的解决方案(前端到后端):
我的问题:当我在我的网络 API 上启用 windows 身份验证时,我无法从我的 React 应用程序获取调用到我的 .NET Core 3.1 网络 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.Controller(s):
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 组件获取调用示例:
"credential: 'include'"是秘密
await fetch('http://localhost:3000/Foo/getTest', {
method: 'GET',
credentials: 'include'
}).then(resp => resp.json());
1) 在 launchSettings.json 文件(开发设置文件)中将允许 Windows 和匿名身份验证标志设置为 true。
匿名身份验证:需要允许飞行前选项请求。
{
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iis":
...
}
2) 在Configure service方法中添加Cors Policy
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 的开发环境中对我有用,IIS Express 具有 Windows 身份验证。
请注意,CORS 中间件在 IIS 中不起作用,请参阅此帖子 here
- 安装CORS module in IIS
- 改造你的 web.config(顺便说一句,我使用的是 .net core 3.1)
- 在您的应用的根目录中添加
web.release.config
- 遵循此 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>
- 在 IIS 中部署您的应用程序