BlazorServer 基于自带的Authentication和Authorization实现自定义权限验证

Program.cs 配置

builder.Services.AddScoped<AuthenticationStateProvider, WebAuthenticationStateProvider>();
builder.Services.AddCascadingAuthenticationState();

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Account/Login";
        options.LogoutPath = "/Account/Logout";
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
        options.SlidingExpiration = true;
    });
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<IAuthorizationHandler,WebAuthorizationHandler>();

// 注意顺序
app.UseAuthentication();
app.UseAuthorization();

Routes.razor 修改

<CascadingAuthenticationState>
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView Resource="routeData" RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)">
                <NotAuthorized>
                    @if (context.User.Identity.IsAuthenticated == false)
                    {
                        <RedirectToLogin/>
                    }
                    else
                    {
                        未授权提示
                    }
                </NotAuthorized>
                
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="routeData" Selector="h1"/>
        </Found>
    </Router>
</CascadingAuthenticationState>

RedirectToLogin 是自动跳转登录

@inject NavigationManager NavigationManager

@code {
    [CascadingParameter] HttpContext _httpContext { get; set; } = default!;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        var returnUrl = Uri.EscapeDataString(NavigationManager.Uri);
        NavigationManager.NavigateTo($"/Account/Login?returnUrl={returnUrl}", forceLoad: true);
    }

}

 

登录验证

public class WebAuthenticationStateProvider : AuthenticationStateProvider
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public WebAuthenticationStateProvider(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var user = _httpContextAccessor.HttpContext.User ?? new ClaimsPrincipal(new ClaimsIdentity());
        return Task.FromResult(new AuthenticationState(user));
    }

    public async Task LoginAsync(UserSession userSession)
    {
        await _httpContextAccessor.HttpContext!.SignInAsync(new ClaimsPrincipal(new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.Name, userSession.Name),
            new Claim(ClaimTypes.Role, userSession.Role),
        }, "WebAuth")));
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }

    public async Task LogoutAsync()
    {
        await _httpContextAccessor.HttpContext!.SignOutAsync();
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }
}

授权验证

public class WebAuthorizationHandler : AuthorizationHandler<IAuthorizationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IAuthorizationRequirement requirement)
    {
        if (context.User.Identity?.IsAuthenticated != true)
        {
            return Task.CompletedTask;
        }

        if (context.Resource is Microsoft.AspNetCore.Components.RouteData routeData)
        {
            var routeAttr = routeData.PageType.CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(RouteAttribute));
            if (routeAttr == null)
            {
                context.Succeed(requirement);
            }
            else
            {
                var url = routeAttr.ConstructorArguments[0].Value as string;
                if (checkUrl(url))
                {
                    context.Succeed(requirement);
                }
                else
                {
                    context.Fail();
                }
            }
        }
        else if (context.Resource is HttpContext httpContext)
        {
            var url = httpContext.Request.Path.Value;
            if (checkUrl(url))
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }

        return Task.CompletedTask;
    }
}

 

checkUrl 方法中根据需要对url进行授权验证即可

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注