ASP.Net 核心中的自定义身份验证机制
Custom Authentication mechanism in ASP.Net Core
我需要从登录页面使用外部 API 对我的用户进行身份验证。如果来自外部的身份验证 API 成功,那么我会在会话中存储一个 AuthToken。
为了检查请求是否有效,我创建了以下授权处理程序
public class ExtApiStoreRequirement : IAuthorizationRequirement
{
}
public class ExtApiAuthorizationHandler : AuthorizationHandler<ExtApiStoreRequirement>
{
IHttpContextAccessor _accessor;
public ExtApiAuthorizationHandler(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ExtApiStoreRequirement requirement)
{
var authState = GET_AUTH_FROM_SESSION(_accessor.HttpContext.Session);
if (authState!=null)
{
_accessor.HttpContext.Response.Redirect("/Account/Login");
//context.Fail(); <-- I removed that because it was responding an empty page
context.Succeed(requirement);
}
else
context.Succeed(requirement);
return Task.CompletedTask;
}
}
而且我已经在我的 startup.cs
注册了这个处理程序
services.AddAuthorization(options =>
{
options.AddPolicy("ExtApi",
policy => policy.Requirements.Add(new ExtApiStoreRequirement()));
});
这种方法有效,但我没有信心,因为我必须调用 context.Succeed(requirement);
才能使重定向起作用。如果我调用 context.Fail()
,则不会发生重定向,我看到的只是一个空页面。
这种方法是否存在任何安全问题,或者我可以安全地使用它?
您的实施是为了授权而不是身份验证。我认为编写自定义身份验证中间件不是创建授权策略,而是适合您的情况。
先看看如何实现自定义认证
要为您的案例实施上述方式 HandleAuthenticateAsync
应该如下所示:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
AuthenticateResult result = null;
var principal = GetPrincipalFromSession();
if(principal != null)
{
result = AuthenticateResult.Success(new AuthenticationTicket(principal,
new AuthenticationProperties(), Options.AuthenticationScheme));
}
else
{
result = AuthenticateResult.Skip();
}
return result;
}
根据评论更新:
protected override async Task<bool> HandleUnauthorizedAsync(ChallengeContext context)
{
Response.Redirect(Options.LoginPath);// you need to define LoginPath
return true;
}
您还应该在用户登录时将主体存储在会话中。
我需要从登录页面使用外部 API 对我的用户进行身份验证。如果来自外部的身份验证 API 成功,那么我会在会话中存储一个 AuthToken。
为了检查请求是否有效,我创建了以下授权处理程序
public class ExtApiStoreRequirement : IAuthorizationRequirement
{
}
public class ExtApiAuthorizationHandler : AuthorizationHandler<ExtApiStoreRequirement>
{
IHttpContextAccessor _accessor;
public ExtApiAuthorizationHandler(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ExtApiStoreRequirement requirement)
{
var authState = GET_AUTH_FROM_SESSION(_accessor.HttpContext.Session);
if (authState!=null)
{
_accessor.HttpContext.Response.Redirect("/Account/Login");
//context.Fail(); <-- I removed that because it was responding an empty page
context.Succeed(requirement);
}
else
context.Succeed(requirement);
return Task.CompletedTask;
}
}
而且我已经在我的 startup.cs
注册了这个处理程序 services.AddAuthorization(options =>
{
options.AddPolicy("ExtApi",
policy => policy.Requirements.Add(new ExtApiStoreRequirement()));
});
这种方法有效,但我没有信心,因为我必须调用 context.Succeed(requirement);
才能使重定向起作用。如果我调用 context.Fail()
,则不会发生重定向,我看到的只是一个空页面。
这种方法是否存在任何安全问题,或者我可以安全地使用它?
您的实施是为了授权而不是身份验证。我认为编写自定义身份验证中间件不是创建授权策略,而是适合您的情况。
先看看如何实现自定义认证
要为您的案例实施上述方式 HandleAuthenticateAsync
应该如下所示:
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
AuthenticateResult result = null;
var principal = GetPrincipalFromSession();
if(principal != null)
{
result = AuthenticateResult.Success(new AuthenticationTicket(principal,
new AuthenticationProperties(), Options.AuthenticationScheme));
}
else
{
result = AuthenticateResult.Skip();
}
return result;
}
根据评论更新:
protected override async Task<bool> HandleUnauthorizedAsync(ChallengeContext context)
{
Response.Redirect(Options.LoginPath);// you need to define LoginPath
return true;
}
您还应该在用户登录时将主体存储在会话中。