.Net 5 Windows 和自定义身份验证

.Net 5 Windows and Custom Auth

我正在 .Net 5.0 上编写 Razor Pages 应用程序 运行。此应用程序需要能够支持工作人员(使用 Windows 身份验证登录)和申请人(没有 Windows 帐户,因此需要 register/login 使用自定义身份验证过程)。我可以得到 Windows 授权或自定义授权来工作,但两者不想一起玩!!

我认为我需要编写 IAuthenticationService 的自定义实现,但这正是它让我失望的地方。我想不出在 ChallengeAsync 中我需要做什么才能让挑战通过!

这是目前的 AuthService 实现(是的,它不是最好的,但我现在的重点是让它工作!!):


    public class AuthService : IAuthenticationService
        {
            async Task<AuthenticateResult> IAuthenticationService.AuthenticateAsync(HttpContext context, string scheme)
            {
                if (HasAnonymousAttribute(context))
                {
                    return AuthenticateResult.NoResult();
                }
    
                var user = getUser(context);
                if (user != null)
                {
                    var ticket = new AuthenticationTicket(user, "magic");
                    return AuthenticateResult.Success(ticket);
                }
    
    
                await context.ChallengeAsync("Windows");
    
                if (context.User.Identity.IsAuthenticated)
                {
                    var ticket = new AuthenticationTicket(context.User, "Windows");
                    return AuthenticateResult.Success(ticket);
                }
    
                return AuthenticateResult.Fail("Please log in");
            }
    
            Task IAuthenticationService.ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
            {
                var user = context.Session.Get("User");
                if (user == null)
                {
                    //do something to block the user from access
                }
    
                return Task.FromResult(0);
            }
    
            Task IAuthenticationService.ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)
            {
                throw new NotImplementedException();
            }
    
            Task IAuthenticationService.SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
            {
                if(scheme.ToLower() == "magic")
                {
                    context.Session.Set("User", Encoding.ASCII.GetBytes(principal.Identity.Name));
                }
    
                return Task.FromResult(0);
    
            }
    
            Task IAuthenticationService.SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
            {
                throw new NotImplementedException();
            }
    
            private ClaimsPrincipal getUser(HttpContext context)
            {
                if (context.User.Identity.IsAuthenticated)
                {
                    return (ClaimsPrincipal)context.User.Identity;
                }
                return null;
    
            }
    
            private bool HasAnonymousAttribute(HttpContext context)
            {
                var endpoint = context.GetEndpoint();
                var retVal = (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null);
    
                return retVal;
            }
        }

您应该只实现需要自定义逻辑的方法。

因此,您可以将常规 Asp.Net AuthenticationService 子类化,然后将自定义逻辑放入 AuthenticateAsync 但不要覆盖 ChallengeAsync,而不是实现接口。

using Microsoft.AspNetCore.Authentication;

namespace Some.Lovely.Namespace
{
    public class MyCustomAuthenticationService : AuthenticationService
    {
        public CustomAuthenticationService(
            [NotNull] IAuthenticationSchemeProvider schemes,
            [NotNull] IAuthenticationHandlerProvider handlers,
            [NotNull] IClaimsTransformation transform,
            [NotNull][ItemNotNull] IOptions<AuthenticationOptions> options) :
base(schemes, handlers, transform, options)
        { }

        public override async Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string? scheme)
        {
            // your custom logic
        }
    }
}

然后在Startup.cs中像这样注册服务:

services.AddScoped<IAuthenticationService, MyCustomAuthenticationService >();