如何在 blazor 页面上使用 usermanager?

how to use usermanager on a blazor page?

你好社区我有一个问题如何在 blazor 页面 webassembly 中使用 usermanager?通过注入:

@inject UserManager<ApplicationUser> UserManager;

我得到的指示是缺少使用指令,因为 class ApplicationUser class 在服务器上,而客户端无法访问服务器。

这是我在 blazor 页面中的代码:

@page "/index"
@inject AuthenticationStateProvider AuthenticationStateProvider
@using Microsoft.AspNetCore.Identity;
@inject UserManager<ApplicationUser> UserManager;

<button @onclick="@LogUsername">Write user info to console</button>
<br />
<br />
@Message

@code {
    string Message = "";

    private async Task LogUsername()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            var currentUser = await UserManager.GetUserAsync(user);
            Message = ($"{user.Identity.Name} is authenticated.{ currentUser.Nombre }");
        }
        else
        {
            Message = ("The user is NOT authenticated.");
        }
    }
}

这是我的 class ApplicationUser:

    public class ApplicationUser: IdentityUser
        {
            public string Nombre { get; set; }
            public string ApellidoPaterno { get; set; }
            public string ApellidoMaterno { get; set; }
            public virtual Cliente InquilinoActual { get; set; }
        }

您不能使用 WebAssembly Blazor 应用中的 UserManager,因为它在浏览器上是 运行。一般来说,您不能在 WebAssembly Blazor 应用程序中使用与数据库访问相关的对象。相反,您通常创建 Web Api 操作方法,并使用 Fetch API (HttpClient).

访问这些方法

您想从用户对象中提取什么值?

什么是 Nombre

无论 Nombre 是什么,您都可以将此值 (Nombre) 添加为声明并从 authState.User

访问它

更新

首先,您应该创建一个名为 ApplicationUserClaimsPrincipalFactory 的服务 class,用于将 table 列的值从用户 table 转换为添加到 ClaimsPrincipal 对象的声明传递给 Blazor 客户端。

(服务器应用程序)ApplicationUserClaimsPrincipalFactory.cs

using AuthenticationStateProviderCustomClaims.Server.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;


public class ApplicationUserClaimsPrincipalFactory : 
                       UserClaimsPrincipalFactory<ApplicationUser>
    {
        public ApplicationUserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, 
                                  IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor)
        {
        }

        protected override async Task<ClaimsIdentity> 
                 GenerateClaimsAsync(ApplicationUser user)
        {
            ClaimsIdentity claims = await 
                            base.GenerateClaimsAsync(user);

            
            claims.AddClaim(new Claim("name", user.Nombre));
            
            return claims;
        }
        
    }

Startup.ConfigureServices

将以下内容放在 .AddDBContext 下方:

services.AddScoped<ApplicationUserClaimsPrincipalFactory>();

            services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddClaimsPrincipalFactory<ApplicationUserClaimsPrincipalFactory>();

services.AddIdentityServer() .AddApiAuthorization(options => {

  // Note: This settings may be superfluous as the name claim 
  // is added by default.              
  options.IdentityResources["openid"].UserClaims.Add("name"); 
  options.ApiResources.Single().UserClaims.Add("name");  

          });

  services.AddAuthentication().AddIdentityServerJwt();

客户端

运行 这段代码,看看它是否有效...如果不能,请 post 完成错误报告

Index.razor

@page "/"

@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider

<p>@_authMessage</p>

@if (_claims != null && _claims.Count() > 0)
{
    <ul>
        @foreach (var claim in _claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@_nombreMessage</p>


@code {
    private string _authMessage;
    private string _nombreMessage;
    private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity.IsAuthenticated)
        {
            _authMessage = $"{user.Identity.Name} is authenticated.";
            _claims = user.Claims;
            _nombreMessage =
            $"Nombre: {user.FindFirst(c => c.Type == ClaimTypes.Name)?.Value}";
        }
        else
        {
            _authMessage = "The user is NOT authenticated.";
        }
    }
    protected override async Task OnInitializedAsync()
    {
        await GetClaimsPrincipalData();
    }
}