如何在 blazor 页面上使用用户管理器?

Posted

技术标签:

【中文标题】如何在 blazor 页面上使用用户管理器?【英文标题】:how to use usermanager on a blazor page? 【发布时间】:2021-03-31 11:47:25 【问题描述】:

你好社区我有一个问题,我如何在 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; 
        

【问题讨论】:

github.com/BrianLParker/AuthApp 自定义应用程序用户并将其作为声明传递.... 【参考方案1】:

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

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

Nombre 是什么?

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

更新

首先,您应该创建一个名为 ApplicationUserClaimsPrincipalFactory 的服务类,该类用于将表列的值从用户表转换为添加到传递给 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(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();

客户端

运行此代码,看看它是否工作......如果没有,请发布完整的错误报告

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 不同 如何在 blazor 页面中使用和注入声明? 你首先必须告诉我 Nombre 代表什么,在什么数据库表中可以找到它... 在aspnetuser表中可以找到name属性,是用户注册时的名字,我问他的名字和姓氏,用user.Identity.Name我从aspnetuser 表,但我想要我包含在 aspnetuser 表中的 Name 属性,用图像编辑我的问题 它工作得很好,现在我可以请求我的声明的属性

以上是关于如何在 blazor 页面上使用用户管理器?的主要内容,如果未能解决你的问题,请参考以下文章

Blazor:如何存储页面状态(所有组件状态)?

Blazor - 在 API 调用时显示等待或微调器

使用ssm(系统存储管理器)进行逻辑管

服务器端 Blazor:刷新页面后如何保持用户身份验证?

使用 Blazor 向其他浏览器发送通知

如何使用 Blazor Server 对用户进行身份验证