ASP.Net Core 2.1中间件WindowsPrincipal ClaimsPrincipal

时间:2019-03-26 13:01:04

标签: c# asp.net-core-2.1 asp.net-core-middleware

情况:我有一个(仅内部网)网站,该网站利用用户名/密码登录。也可以使用Windows用户登录。

我要做什么:当用户转到该网站上的页面并且尚未使用用户名/密码登录时,该用户将使用Windows身份验证登录。这导致他的HttpContext.User对象的类型为WindowsPrincipal。然后,我通过SignInManager<User>.SignInAsync()自动将用户登录到其相应的用户。现在,用户拥有我数据库中指定的所有角色,而不是AD赋予的角色。

当前方法的问题:最初,我仅在默认开始页面上进行过此重写。因此,我可以在部分完成签名后明确重新加载此页面。如果用户转而转到另一个子页面(例如,通过书签),则将跳过身份验证类型的重写=>他停留为WindowsPrincipal

我尝试的解决方法:通过中间件部分登录。我有一个服务(实现IMiddleware,比较https://stackoverflow.com/a/52214120/2968106),该服务在其InvokeAsync()方法中进行此操作。

我的解决方案存在的问题:以用户身份使用我的中间件登录太晚了,因此该页面返回“访问被拒绝”,因为该用户当时缺少所需的角色。再次加载页面可以解决此问题。我在ConfigureStartup.cs之后的app.UseAuthentication()的{​​{1}}方法中调用了中间件。在这两个位置之前移动它不会改变任何内容。

问题:a)这种方法可行吗? b)我应该在何时调用此方法,或者在登录完成后,是否有一种方法可以从中间件内部完整请求所有参数的给定页面?

关于b):是否有某种功能可以从头开始重新启动管道,我可以在app.UseSession()之后在中间件中调用它?

修改

1)我的中间件

SignInAsync()

2)public class WindowsPrincipalToClaimPrincipal :IMiddleware { private readonly SignInManager<User> _signInManager; private readonly UserService _userService; public WindowsPrincipalToClaimPrincipal(SignInManager<User> signInManager, UserService userService) { _signInManager = signInManager; _userService = userService; } public Task InvokeAsync(HttpContext context, RequestDelegate next) { if (context.User is WindowsPrincipal) { _signInManager.SignInAsync(_userService.GetCurrentUser(), false).Wait(); } return next(context); } }

的相关部分
Startup.cs

1 个答案:

答案 0 :(得分:0)

似乎答案比预期的要容易。如果此方法在所有情况下都能按预期工作,我将不得不进行更详细的尝试,但在短期内,我发现了以下可能的解决方案:

在中间件中,在SignInAsync()之后添加以下行:

context.User = _signInManager.CreateUserPrincipalAsync(_userService.GetCurrentUser()).Result;

我已经习惯了只读用户(例如使用PageModel.User时),以至于我甚至都没有想到写该属性的可能性。

编辑:另一个要点:不要过早调用中间件。应该在app.useAuthentication()之后调用它,否则您将失去使用普通帐户登录的能力。