繁体   English   中英

ASP.Net Core 2.1中间件WindowsPrincipal ClaimsPrincipal

[英]ASP.Net Core 2.1 Middleware WindowsPrincipal ClaimsPrincipal

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

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

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

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

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

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

关于b):是否有某种函数可以从头开始重新启动管道,可以在SignInAsync()之后在中间件中调用该SignInAsync()

编辑

1)我的中间件

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);
    }
}

2) Startup.cs相关部分

//At the end of ConfigureServices()
services.AddScoped<WindowsPrincipalToClaimPrincipal>();

//Inside Configure(), before app.UseMvc(...);
app.UseAuthentication();
app.UseSession();
app.UseMiddleware<WindowsPrincipalToClaimPrincipal>(); //moving this line to the beginning of Configure() doesn't change anything.

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

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

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

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

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

暂无
暂无

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

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