我有一个带有自定义
AuthorizationHandler
和 IAuthorizationRequirement
的 Blazor 应用程序。片段来自AuthorizationHandler
:
internal class PermissionLevelAuthorizationHandler : AuthorizationHandler<PermissionLevelRequirement>
{
private readonly AuthService _authService;
public PermissionLevelAuthorizationHandler(AuthService authService)
{
_authService= authService;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionLevelRequirement requirement)
{
string? requiredResource = ((DefaultHttpContext?)context.Resource)?.Request.Path;
int requiredLevel = requirement.Level;
var canAccess = _authService.GetPermission(requiredResource, context.User, requiredLevel);
if (canAccess) {
context.Succeed(requirement);
}
}
}
AuthorizationHandler
已注入 AuthService
,它做了两件事:
从数据库中获取当前用户所属的所有组
检查(再次在数据库中)是否有任何用户组可以使用所需的权限级别访问所需的页面。
AuthService
和AuthorizationHandler
都是范围服务。
由于
AuthService
必须为每个授权检查执行两次查询,因此我想将当前用户权限存储在 AuthService
中,并且仅在尚未加载权限时才联系数据库。
问题:问题是,似乎
AuthorizationHandler
每次都会获得AuthService
的新实例,即使它们都在作用域内。因此我无法在服务中存储任何数据。为什么会这样?有什么办法可以解决这个问题吗?有没有更好的方法可以做到这一点?
据我所知,替代方案是:
此外,身份验证是由中央应用程序完成的。因此身份验证 cookie 在多个应用程序之间共享。这使得存储变得更加复杂,因为我必须在所有应用程序上正确处理数据删除。这就是为什么最好的解决方案似乎是将数据存储在 DI 服务实例中。
Blazor Server 中的范围通常会根据连接进行持久化。
但是,如果我正确理解官方文档(请参阅https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/dependency-injection?view=aspnetcore-8.0#service-lifetime),有一个例外,那就是
“在客户端加载的组件之间传递消息”。
我假设您的逻辑是在这些电路消息的范围内执行的,因此,您的作用域服务的服务实例不会持久化,这可以解释您所经历的行为。
我建议实现单例缓存(就像您已经提到的那样)来安全地保存数据。