如何为 Blazor 页实现自定义授权筛选器



Blazor 服务器端,.NET Core 3.1.x 查看有关授权的示例,我正在尝试获得自定义授权过滤器/属性的解决方案。 我只需要在授权期间检查用户身份。

https://learn.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.1

在 Blazor 页面顶部,@page之后

@attribute [MyAuthFilter]

筛选器。 然而,OnAuthorization永远不会受到打击。

public class MyAuthFilter: AuthorizeAttribute,IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var httpContext = context.HttpContext;

// get user name
string userName = httpContext.User.Identity.Name;
// todo - call method to check user access
// check against list to see if access permitted
//context.Result = new UnauthorizedResult();
}
}

以下代码片段介绍如何执行授权过程,以及如何以及在何处为授权用户显示内容。您可以根据此处显示的代码构建自己的组件:

Profile.razor

@page "/profile"
@page "/profile/{id}"

<AuthorizeView Policy="CanEditProfile" Resource="@ID">
<NotAuthorized>
<h2 class="mt-5">You are not authorized to view this page</h2>
</NotAuthorized>
<Authorized>
<div class="container my-profile">
<h2>My Profile</h2>
--- Place here all the content you want your user to view ----
</div>
</Authorized>
</AuthorizeView>
@code {
[Parameter]
public string ID { get; set; }
}  

配置文件处理程序.cs

public class ProfileHandler : IAuthorizationHandler
{
public Task HandleAsync(AuthorizationHandlerContext context)
{
if (context.User != null)
{
var pendingRequirements = context.PendingRequirements.ToList();
foreach (var requirement in pendingRequirements)
{
if (requirement is ProfileOwnerRequirement)
{
// get profile id from resource, passed in from blazor 
//  page component
var resource = context.Resource?.ToString();
var hasParsed = int.TryParse(resource, out int 
profileID);
if (hasParsed)
{
if (IsOwner(context.User, profileID))
{
context.Succeed(requirement);
}
}
}
}
}
return Task.CompletedTask;
}
private bool IsOwner(ClaimsPrincipal user, int profileID)
{
// compare the requested memberId to the user's actual claim of 
// memberId
//  var isAuthorized = context.User.GetMemberIdClaim();
// now we know if the user is authorized or not, and can act 
// accordingly
var _profileID = user.GetMemberIDClaim();

return _profileID == profileID;
}
}

配置文件所有者要求.cs

public class ProfileOwnerRequirement : IAuthorizationRequirement
{
public ProfileOwnerRequirement() { }
}

启动类

services.AddSingleton<IAuthorizationHandler, ProfileHandler>();
services.AddAuthorization(config =>
{
config.AddPolicy("CanEditProfile", policy =>
policy.Requirements.Add(new ProfileOwnerRequirement()));
});

希望这有帮助!

如果你只想验证一种需求,你可以简化@enet响应替换 ProfileHandler.cs:

public class ProfileHandler : AuthorizationHandler<ProfileOwnerRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ProfileOwnerRequirement requirement)
{
if (context.User.Identity.IsAuthenticated)
{               
var resource = context.Resource?.ToString();

var hasParsed = int.TryParse(resource, out int 
profileID);
if (hasParsed)
{
if (IsOwner(context.User, profileID))
{
context.Succeed(requirement);
}
}                                
}
return Task.CompletedTask;
}
private bool IsOwner(ClaimsPrincipal user, int profileID)
{        
var _profileID = user.GetMemberIDClaim();
return _profileID == profileID;
}
}

使用HandleRequirementsAsync,它只被调用一次,而如果你使用HandleAsync,它会被调用多次,当然对于简单的验证没有区别,但如果你有复杂的验证,它们将被多次运行。

最新更新