【问题标题】:How to implement custom authorization filter for Blazor page如何为 Blazor 页面实现自定义授权过滤器
【发布时间】:2020-09-09 13:54:13
【问题描述】:

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

https://docs.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();

    }
}

【问题讨论】:

标签: blazor blazor-server-side


【解决方案1】:

以下代码 sn-p 描述了如何执行授权过程,以及如何以及在何处为授权用户显示内容。您可以根据此处显示的代码构建自己的组件:

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; }
}  

ProfileHandler.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;
     }

 }

ProfileOwnerRequirement.cs

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

 }

启动类

services.AddSingleton<IAuthorizationHandler, ProfileHandler>();

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

希望这会有所帮助!

【讨论】:

  • 好的,谢谢!我现在已经朝着那个方向走了。在这里查看我的另一篇文章,由于某种原因,我的处理程序代码没有被调用。 stackoverflow.com/questions/61963205/… 我真的不需要隔离的授权/未授权内容,而只是想做一些关于授权的自定义逻辑,所以你展示的不同之处在于我使用页面级授权属性@attribute [Authorize(Policy = Policies. IsValidUser)]
【解决方案2】:

如果您只是想验证一种需求,您可以简化@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;
     }
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多