【问题标题】:ASP.NET Core Identity with Windows Authentication带有 Windows 身份验证的 ASP.NET Core 标识
【发布时间】:2019-07-03 19:52:23
【问题描述】:

我正在使用 .NET Core 3.0 Preview6。
我们有一个启用了 Windows 身份验证的 Intranet 应用程序,这意味着只有有效的 AD 用户才能使用该应用程序。
但是,我们喜欢使用 ASP.NET Identity 运行我们自己的身份验证后端,因为它“开箱即用”。我刚刚在 AspNetUsers 表中添加了一个包含用户 Windows 登录名的列。

我想要完成的是,Windows 用户会自动使用他们的 Windows 登录名登录到应用程序。
我已经创建了一个自定义的身份验证中间件,请参见下面的代码:

public class AutoLoginMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public AutoLoginMiddleware(RequestDelegate next, ILogger<AutoLoginMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context, UserService userService, UserManager<IntranetUser> userManager, 
        SignInManager<IntranetUser> signInManager)
    {
        if (signInManager.IsSignedIn(context.User))
        {
            _logger.LogInformation("User already signed in");
        }
        else
        {
            if (context.User.Identity as WindowsIdentity != null)
            {
                _logger.LogInformation($"User with Windows Login {context.User.Identity.Name} needs to sign in");
                var windowsLogin = context.User.Identity.Name;


                var user = await userManager.Users.FirstOrDefaultAsync(u => u.NormalizedWindowsLogin == windowsLogin.ToUpperInvariant());

                if (user != null)
                {
                    await signInManager.SignInAsync(user, true, "automatic");
                    _logger.LogInformation($"User with id {user.Id}, name {user.UserName} successfully signed in");

                    // Workaround
                    context.Items["IntranetUser"] = user;
                }
                else
                {
                    _logger.LogInformation($"User cannot be found in identity store.");
                    throw new System.InvalidOperationException($"user not found.");
                }
            }
        }

        // Pass the request to the next middleware
        await _next(context);
    }
}

文档说SignInManager.SignInAsync 创建了一个新的ClaimsIdentity - 但似乎从未发生过 - HttpContext.User 始终保持为WindowsIdentity。在用户再次登录的每个请求中,对signInManager.IsSignedIn() 的调用总是返回false。

我现在的问题是:以这种方式进行自动身份验证通常是个好主意吗?还有哪些其他方式存在?

我的下一个要求是有一个自定义的AuthorizationHandler。 这里的问题是,有时在HandleRequirementAsync 方法中AuthorizationHandlerContext.User.IdentityWindowsIdentity,然后对context.User.Identity.Name 的调用会引发以下异常:

System.ObjectDisposedException: Safe handle has been closed.

Object name: 'SafeHandle'.

   at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)

   at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)

   at Interop.Advapi32.GetTokenInformation(SafeAccessTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, UInt32& ReturnLength)

   at System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeAccessTokenHandle tokenHandle, TokenInformationClass tokenInformationClass, Boolean nullOnInvalidParam)

   at System.Security.Principal.WindowsIdentity.get_User()

   at System.Security.Principal.WindowsIdentity.<GetName>b__51_0()

   at System.Security.Principal.WindowsIdentity.<>c__DisplayClass67_0.<RunImpersonatedInternal>b__0(Object <p0>)

   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)

我现在的假设是这两个部分不能很好地协同工作。有时似乎存在时间问题 - 我的自定义 AuthorizationHandler 在调用 AutoLoginMiddleware 之间被调用

【问题讨论】:

  • 我在尝试调用 middlewares.AutoLoginMiddleware 时收到“无法解析类型 'Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser] 的服务”。你知道如何解决这个问题?启动有 app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware();
  • 我猜你忘了注册身份框架:services.AddDefaultIdentity&lt;IdentityUser&gt;() 应该可以解决问题。
  • 我做到了。这是我的 ConfigureServices() services.AddIdentity(options => { options.User.RequireUniqueEmail = true;
  • 然后您必须将 UserManager 作为参数添加到 AutoLoginMiddleware InvokeAsync 方法。从您的错误消息看来,您错误地添加了错误的 UserManager
  • 我正在研究一个几乎相同案例的解决方案,而您的 AutoLoginMiddleware 的想法正是我所需要的。但是,一旦我添加 .AddIdentity(),context.User.Identity 就永远不会返回 WindowsIdentity - 它总是来自 ClaimsIdentity 类型。任何提示我错过了什么?

标签: c# asp.net-core windows-authentication asp.net-core-identity


【解决方案1】:

现在已修复。这是预览版中的一个错误。现在它按预期工作。祝你好运!

更新:我想发布我的 .NET Core 3.1 Final 工作代码。

  1. 必须在Configure的框架中间件之后注册自定义登录中间件:
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseMiddleware<AutoLoginMiddleware>();
  1. 在自定义中间件中,用户登录后必须调用CreateUserPrincipalAsync并将此主体保存到HttpContext.User属性中。

    await signInManager.SignInAsync(user, true);
    context.User = await signInManager.CreateUserPrincipalAsync(user);
    
  2. 对于 Blazor,我们必须使用 AuthenticationStateProvider。它有一个属性User,其中包含来自HttpContextClaimsPrincipal。就是这样。

  3. 您现在可以像下面这样获取身份用户:

    var authState = await _authenticationStateProvider.GetAuthenticationStateAsync();
    var intranetUser = await UserManager.GetUserAsync(authState.User);
    

【讨论】:

    猜你喜欢
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多