【发布时间】:2020-06-05 00:53:14
【问题描述】:
我正在尝试迁移使用这种东西的旧 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");
});
}
我有一个自定义过滤器,我需要从中获取当前用户的身份,并验证它是否具有与之关联的某个 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 不同。哪个确实识别出以下序列
- NTLM 密码错误,401 未经授权
- NTLM 好密码,200 OK
- NTLM 密码错误,401 未经授权
还有什么我需要在某个地方设置的吗?有人对此有任何线索吗?
【问题讨论】:
标签: asp.net-core postman asp.net-core-webapi asp.net-core-3.1