.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 >();
我正在 .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 >();