Blazor WebAssembly 与身份服务器通过表单传递用户名

Posted

技术标签:

【中文标题】Blazor WebAssembly 与身份服务器通过表单传递用户名【英文标题】:Blazor WebAssembly with identity server passing username through form 【发布时间】:2022-01-10 23:47:36 【问题描述】:

我是 Blazor WebAssembly 的新手。我有一个简单的页面,允许用户注册公司。它需要公司名称、描述和用户名。目前用户名是由用户输入的,但我想自动获取登录用户的用户名并在不需要用户输入的情况下发布它。这是我的页面:

@page "/companies/create"

@attribute [Authorize]
@inject HttpClient Http
@inject NavigationManager Navigation


<h3>Register your company</h3>
<AuthorizeView>
    Hello, @context.User.Identity.Name!
</AuthorizeView>
<EditForm Model="Companies" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />

    <div class="form-group">
        <label class="control-label">Name</label>
        <InputText @bind-Value="Companies.Name" class="form-control" />
        <ValidationMessage For="@(() => Companies.Name)" />
    </div>

    <div class="form-group">
        <label class="control-label">Description</label>
        <InputText @bind-Value="Companies.Description" class="form-control" />
        <ValidationMessage For="@(() => Companies.Description)" />
    </div>
    <div class="form-group">
        <label class="control-label">Username</label>
        <InputText @bind-Value="Companies.Username" class="form-control"/>
        <ValidationMessage For="@(() => Companies.Username)" />
    </div>


    <button type="submit" class="btn btn-primary">
        <i class="fas fa-save"></i> Register
    </button>
</EditForm>


@code 
    private Sprelo.Shared.Companies Companies  get; set;  = new Sprelo.Shared.Companies();

    private async void HandleValidSubmit()
    
        try
        

            var response = await Http.PostAsJsonAsync($"/api/companies", Companies);
            response.EnsureSuccessStatusCode();

            var content = await response.Content.ReadAsStringAsync();
            var companies = JsonConvert.DeserializeObject<Sprelo.Shared.Companies>(content);
            Navigation.NavigateTo($"Companies/edit/companies.Id");
        
        catch (AccessTokenNotAvailableException exception)
        
            exception.Redirect();
        
        catch (Exception e)
        

        
    

这是我的模型:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sprelo.Shared

    public class Companies
    
        [Key]
        public Guid Id  get; set; 

        [Required]
        public String Name  get; set; 
        public String Description  get; set; 
        public String Username  get; set; 
    

这是一个自动生成的 API 控制器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Sprelo.Server.Data;
using Sprelo.Shared;

namespace Sprelo.Server.Controllers

    [Route("api/[controller]")]
    [ApiController]
    public class CompaniesController : ControllerBase
    
        private readonly ApplicationDbContext _context;

        public CompaniesController(ApplicationDbContext context)
        
            _context = context;
        

        // GET: api/Companies
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Companies>>> GetCompanies()
        
            return await _context.Companies.ToListAsync();
        

        // GET: api/Companies/5
        [HttpGet("id")]
        public async Task<ActionResult<Companies>> GetCompanies(Guid id)
        
            var companies = await _context.Companies.FindAsync(id);

            if (companies == null)
            
                return NotFound();
            

            return companies;
        

        // PUT: api/Companies/5
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPut("id")]
        public async Task<IActionResult> PutCompanies(Guid id, Companies companies)
        
            if (id != companies.Id)
            
                return BadRequest();
            

            _context.Entry(companies).State = EntityState.Modified;

            try
            
                await _context.SaveChangesAsync();
            
            catch (DbUpdateConcurrencyException)
            
                if (!CompaniesExists(id))
                
                    return NotFound();
                
                else
                
                    throw;
                
            

            return NoContent();
        

        // POST: api/Companies
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPost]
        public async Task<ActionResult<Companies>> PostCompanies(Companies companies)
        
            _context.Companies.Add(companies);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetCompanies", new  id = companies.Id , companies);
        

        // DELETE: api/Companies/5
        [HttpDelete("id")]
        public async Task<IActionResult> DeleteCompanies(Guid id)
        
            var companies = await _context.Companies.FindAsync(id);
            if (companies == null)
            
                return NotFound();
            

            _context.Companies.Remove(companies);
            await _context.SaveChangesAsync();

            return NoContent();
        

        private bool CompaniesExists(Guid id)
        
            return _context.Companies.Any(e => e.Id == id);
        
    

我已经为此苦苦挣扎了很长一段时间,如果有任何帮助,将不胜感激!

【问题讨论】:

【参考方案1】:

AuthenticationStateProvider 对象注入到您的组件中,如下所示:

@inject AuthenticationStateProvider authProvider

重写 OnInitialized 生命周期方法:

protected override void OnInitialized ()

    var authenticationStateTask = await 
                          authProvider.GetAuthenticationStateAsync();
                     
    var user = authenticationStateTask.User;

    // Check if the user is authenticated       
    if (user.Identity.IsAuthenticated)
    
        // Grab the user name and assign it to Companies.Username
        Companies.Username = user.Identity.Name
    

【讨论】:

以上是关于Blazor WebAssembly 与身份服务器通过表单传递用户名的主要内容,如果未能解决你的问题,请参考以下文章

Blazor WebAssembly身份认证与授权

Blazor WebAssembly身份认证与授权

Blazor WebAssembly - 用户帐户和身份服务器的最佳实践

如何在 blazor webassembly 项目中对服务器端控制器中的用户进行身份验证?

Blazor WebAssembly SignalR 身份验证

使用 IdentityServer4、Asp.Net Core Identity 和自定义提供程序进行 Blazor WebAssembly 身份验证,无需实体框架