我正在尝试迁移使用这种东西的旧的OWIN自托管WebApi
var listener = (HttpListener)appBuilder.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
到一个新的.NET Core 3.1项目。我已经读过关于Auth
这就是我的项目文件的样子
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Text.Json" Version="4.7.0" />
</ItemGroup>
</Project>
这就是我的launchsettings.json
的样子
{
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:9600",
"sslPort": 0
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/audit",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"use64Bit": true
},
"Audit.Core": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "api/audit",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:9600"
},
"Azure Dev Spaces": {
"commandName": "AzureDevSpaces",
"launchBrowser": true
}
}
}
这就是我的Startup.cs
的样子
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Server.HttpSys;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NLog;
namespace xxxx
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
services.AddControllers().AddNewtonsoftJson();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
这是Program.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>()
.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.NTLM;
options.EnableResponseCaching = false;
options.Authentication.AllowAnonymous = false;
});
})
.ConfigureWebHost(config =>
{
config.UseUrls("http://*:9600");
});
}
我有一个自定义过滤器,我需要从中获取当前用户的Identity并验证它是否具有与之关联的特定ActiveDirectory组。基本用法是这样的
[ApiController]
[Route("api/some")]
[ControllerExceptionFilter]
public class SomeController : ControllerBase
{
[HttpPost("add")]
[ActiveDirectoryAuthorize("SomeGroup")]
public IActionResult Add([FromBody]SomeEvent s)
{
var user = this.HttpContext.User.Identity;
return Ok("cool");
}
}
过滤器外观如下
//https://stackoverflow.com/questions/31464359/how-do-you-create-a-custom-authorizeattribute-in-asp-net-core
public class ActiveDirectoryAuthorizeAttribute : TypeFilterAttribute
{
public ActiveDirectoryAuthorizeAttribute(string groupMembership) : base(typeof(ActiveDirectoryAuthorizeFilter))
{
Arguments = new object[] { groupMembership };
}
}
public class ActiveDirectoryAuthorizeFilter : IAuthorizationFilter
{
private string _groupMembership;
public ActiveDirectoryAuthorizeFilter(string groupMembership)
{
_groupMembership = groupMembership;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
try
{
Authenticate(context);
}
catch (InvalidWindowsUserException ex)
{
HandleUnauthorizedRequest(context);
}
catch (Exception ex)
{
HandleInternalServerError(context);
}
}
protected void HandleUnauthorizedRequest(AuthorizationFilterContext context)
{
context.HttpContext.Response.Headers.Add("WWW-Authenticate", "NTLM");
context.Result = new ContentResult
{
Content = "Unauthorized",
StatusCode = (int)HttpStatusCode.Unauthorized
};
}
private void HandleInternalServerError(AuthorizationFilterContext context)
{
context.HttpContext.Response.Headers.Add("WWW-Authenticate", "NTLM");
context.Result = new ContentResult
{
Content = "Internal Server Error",
StatusCode = (int)HttpStatusCode.InternalServerError
};
}
private void Authenticate(AuthorizationFilterContext context)
{
var identity = context?.HttpContext?.User?.Identity;
if (identity == null)
{
throw new InvalidWindowsUserException("Access denied");
}
EnsureAdmin(identity);
}
private void EnsureAdmin(IIdentity identity)
{
......
}
}
所有这些都可以启动POSTMAN并使用 BAD 密码发出NTLM请求,我得到一个401。这是预期的
因此,我然后编辑POSTMAN请求以输入正确的密码,然后得到密码,在密码中输入200,并从上面显示的控制器中获得“酷”响应
到目前为止,所有工作均按预期进行。但是,如果我随后更改了当前有效的POSTMAN(200 ok)请求,请再次使用BAD NTLM密码。我原本希望看到401,但是当前用户只是显示为仍在我的自定义过滤器中被授权
此行为与基于OLD OWIN的WebApi不同。哪个确实可以识别以下顺序
我还需要在某处设置其他内容吗?有人对此有任何线索吗?
答案 0 :(得分:1)
我遇到过同样的情况,在我看来,这是一个邮递员问题,就像它“缓存”了好的密码,并且即使您用错误的密码更改了密码一样,也继续发送。
如果您退出并重新进入邮递员,并使用错误的密码重复上一次请求,您将获得“正确的” 401未经授权的信息,即:
1. NTLM bad password -> 401 Unauthorized - correct
2. NTLM good password -> 200 OK - correct
3. NTLM bad password -> 200 OK - WRONG, as if Postman cached the good password
4. Exit Postman - Re-enter Postman
5. NTLM bad password (same as 3.) -> 401 Unauthorized - correct
也许它与NTLM认证机制有关,这暗示着“挑战”,即幕后有一个“谈判”,而Postman透明地处理了多个HTTP调用,但是如果您更改了密码。
编辑:值得一提的是,邮递员中的NTLM身份验证功能当前位于测试版中。