Blazor页面元素授权——AuthorizeView 组件的使用

Blazor页面元素授权——AuthorizeView 组件的使用

上篇博客我们说到了blazor的身份认证的实现,对于AuthorizeView 组件来说,可以通过级联参数来获取包含了用户信息的AuthenticationState对象。

请注意,你需要引用Microsoft.AspNetCore.Components.Authorization Nuget包,并且在启动类中添加服务Services.AddAuthorizationCore();
使用CascadingAuthenticationState组件包裹App.razor中的代码:

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" 
                DefaultLayout="@typeof(MainLayout)" />
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

如果未指定授权条件,则 AuthorizeView 使用默认策略:

  • 将经过身份验证(已登录)的用户视为已授权。
  • 将未经过身份验证(已注销)的用户视为未授权。

基于角色的授权方式

角色的获取方式是多样的,可以来自项目本身,也可以来自外部的权限系统。总之,你需要清楚角色对应的权限本身范围,比如控制了哪些页面可以访问,哪些按钮是可见的。
请记住,仅在客户端进行权限控制并不是安全的。

在AuthorizeView组件中包裹需要验证角色才可以查看的组件

<AuthorizeView Roles="admin">
    <p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

我个人是将认证与授权作为两个服务。授权服务根据系统码以及模块Id,调用权限管理系统接口,权限系统会根据当前用户来返回权限树,而我拿到权限树之后,会将其中的按钮或是页面的权限标识作为Roles,写入AuthenticationState当中,使用上面例子的方式,控制页面元素的展示。

下面附上完整的授权服务代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using ClientSideTemplate.Client.Foundation.Authentication.Model;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.WebAssembly.Http;
using Newtonsoft.Json;

namespace ClientSideTemplate.Client.Foundation.Authentication
{
    public class AuthorizedService
    {
        private readonly IServiceClient _serviceClient;
        private readonly AuthorizedOption _authorizedOption;

        public AuthorizedService(IServiceClient serviceClient, AuthorizedOption authorizedOption)
        {
            _serviceClient = serviceClient;
            _authorizedOption = authorizedOption;
        }

        public async Task AuthorizedAsync(AuthenticationState state)
        {
#if DEBUG
            var identity = new ClaimsIdentity(_authorizedOption.ModuleIds.Select(x => new Claim(ClaimTypes.Role, x)));
            state.User.AddIdentity(identity);
#else
            foreach (var moduleId in _authorizedOption.ModuleIds)
            {
                var userInfo = await GetUserInfo(_authorizedOption.SystemCode, moduleId);
                var identity = new ClaimsIdentity(userInfo.PrivilegeTree.Select(x => new Claim(ClaimTypes.Role, x.ModuleId)));
                state.User.AddIdentity(identity);
            }
#endif
        }

        private async Task<UserInfo> GetUserInfo(string systemCode, string moduleId)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, $"/login/Auth/UserInfo?systemCode={systemCode}&moduleId={moduleId}");
            request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

            var response = await _serviceClient.SendAsync(request);
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
#if !DEBUG
                SignIn();
#endif
            }

            var content = await response.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(content))
            {
                return new UserInfo();
            }

            return JsonConvert.DeserializeObject<ApiResult<UserInfo>>(content).Result;
        }
    }
}

另外,如果你想在代码中获取AuthenticationState,请以级联参数的形式:

 [CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }

猜你喜欢

转载自blog.csdn.net/qq_40404477/article/details/109346470