如何在 Blazor 页面上使用 UserManager?

4

大家好,我有一个问题:如何在 Blazor WebAssembly 页面中使用 usermanager?我应该通过注入以下代码来实现:

@inject UserManager<ApplicationUser> UserManager;

我感到缺少一个使用指令,因为ApplicationUser类在服务器上,而客户端无法访问服务器。
这是我在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.");
        }
    }
}

这是我的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; }
        }

Image of an SQL Query


https://github.com/BrianLParker/AuthApp 自定义应用程序用户并将其作为声明传递... - Brian Parker
1个回答

6
无法在 WebAssembly Blazor 应用程序中使用 UserManager,因为它在浏览器上运行。一般来说,在 WebAssembly Blazor 应用程序中无法使用与数据库访问相关的对象。相反,您通常会创建 Web API 操作方法,并使用 Fetch API(HttpClient)访问这些方法。
您想从用户对象中提取什么值?
“Nombre”是什么?
无论 “Nombre” 是什么,您都可以将此值(“Nombre”)作为声明添加,并从 “authState.User” 访问它。
更新: 首先,您应该创建一个名为 ApplicationUserClaimsPrincipalFactory 的服务类,用于将 Users 表中的表列值转换为添加到传递给 Blazor 客户端的 ClaimsPrincipal 对象中的声明。
(服务器应用程序)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<ApplicationUser, ApplicationDbContext>(options => { //翻译:在这里配置 API 授权 });

  // 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();

客户端

运行此代码并查看是否正常工作...如果不正常,请提供完整的错误报告

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

好的非常好,非常感谢您提供的信息。我想从ApplicationUser中提取名称,我的应用程序中的名称与UserName不同。 - Enrique
如何在 Blazor 页面中使用和注入声明? - Enrique
首先,您必须告诉我“Nombre”代表的是什么意思,以及它可能在哪些数据库表中找到... - enet
在 aspnetuser 表中,您可以找到 name 属性,它是用户注册时的名称。我要求他的名字和姓氏,使用 user.Identity.Name,我可以从 aspnetuser 表中获取 UserName 字段,但我想要包含在 aspnetuser 表中的 Name 属性。请用一张图片编辑我的问题。 - Enrique
1
它现在运行得很完美,我现在可以请求我的索赔的属性。 - Enrique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接