使用.NET 6开发TodoList应用(填坑1)——实现当前登录用户获取


系列导航及源代码

需求

在前面的文章里使用.NET 6开发TodoList应用(5)——领域实体创建,我们留了一个坑还没有填上,就是在数据库保存的时候,CreateUser和ModifiedUser我们当时填的都是Anonymous,完成认证的功能后,现在我们需要实现在保存数据库的时候填入当前登陆进行操作的用户名。

目标

实现当前登陆用户信息获取。

原理和思路

原理很简单,在认证时拿到的Token里,payload中是包含登陆User的部分信息的,作为演示,我们需要想办法获取到用户名信息,并在保存数据时填入相应字段。为了获取Token中包含的用户信息,需要用到HttpContextAccessor对象。很显然,需要一个新的接口和实现。

实现

创建当前用户获取接口

Application/Common/Interfaces中添加一个新的接口:

  • ICurrentUserService.cs
namespace TodoList.Application.Common.Interfaces;

public interface ICurrentUserService
{
    string? UserName { get; }
}

这里我们取的是UserName,是因为在返回的Token中包含UserName的信息,如果需要使用UserId或其他信息,需要在GetClaims中添加:

// 演示了返回用户名和Role两个claims
var claims = new List<Claim>
{
    // Claims中包含UserName信息
    new(ClaimTypes.Name, User!.UserName),
    new(JwtRegisteredClaimNames.Iss, _jwtConfiguration.ValidIssuer ?? "TodoListApi"),
    new(JwtRegisteredClaimNames.Aud, _jwtConfiguration.ValidAudience ?? "http://localhost:5050")
};

实现接口功能

Api/Services中添加类实现接口:

  • CurrentUserService.cs
using System.Security.Claims;
using TodoList.Application.Common.Interfaces;

namespace TodoList.Api.Services;

public class CurrentUserService : ICurrentUserService
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public CurrentUserService(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    // 通过注入的IHttpContextAccessor获取`HttpContext.User(ClaimsPrinciple)`中对应的Claims信息
    public string? UserName  => _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.Name);
}

并在Program中添加依赖注入:

  • Program.cs
builder.Services.AddSingleton<ICurrentUserService, CurrentUserService>();

使用功能

接下来我们去修改DbContext,需要先在构造函数中注入:

  • TodoListDbContext.cs
private readonly ICurrentUserService _currentUserService;
public TodoListDbContext(
    DbContextOptions<TodoListDbContext> options,
    IDomainEventService domainEventService,
    ICurrentUserService currentUserService) : base(options)
{
    _domainEventService = domainEventService;
    _currentUserService = currentUserService;
}

SaveChangesAsync方法中修改:

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
    foreach (var entry in ChangeTracker.Entries<AuditableEntity>())
    {
        switch (entry.State)
        {
            case EntityState.Added:
                entry.Entity.CreatedBy = _currentUserService.UserName;
                entry.Entity.Created = DateTime.UtcNow;
                break;
            case EntityState.Modified:
                entry.Entity.LastModifiedBy = _currentUserService.UserName;
                entry.Entity.LastModified = DateTime.UtcNow;
                break;
        }
    }
// 省略其他...
}

验证

启动Api项目,首先获取Token,再用获取到的Token去创建一个新的TodoList:

img

可以看到新创建的TodoList的用户信息已经获取到了,为了确保数据存储到数据库中,我们去数据库看一下:

img

总结

在本文中我们实现了如何从请求中获取当前登陆的用户信息并保存到数据库中。

文章出处:https://www.cnblogs.com/code4nothing/p/build-todolist-appendix-1.html

版权声明:本文为YES开发框架网发布内容,转载请附上原文出处连接
管理员
上一篇:WPF_15_格式化绑定的数据
下一篇:Microsoft Store 桌面应用发布流程(一)之打包应用
评论列表

发表评论

评论内容
昵称:
关联文章

使用.NET 6开发TodoList应用(1)——实现当前登录用户获取
使用.NET 6开发TodoList应用(25)——实现RefreshToken
使用.NET 6开发TodoList应用(22)——实现缓存
使用.NET 6开发TodoList应用(9)——实现PUT请求
使用.NET 6开发TodoList应用(30)——实现Docker打包和部署
使用.NET 6开发TodoList应用(12)——实现ActionFilter
使用.NET 6开发TodoList应用(7)——使用AutoMapper实现GET请求
使用.NET 6开发TodoList应用(6)——使用MediatR实现POST请求
使用.NET 6开发TodoList应用(31)——实现基于Github Actions和ACI的CI/CD
使用.NET 6开发TodoList应用(16)——实现查询排序
使用.NET 6开发TodoList应用(15)——实现查询搜索
使用.NET 6开发TodoList应用(14)——实现查询过滤
使用.NET 6开发TodoList应用(24)——实现基于JWT的Identity功能
使用.NET 6开发TodoList应用(13)——实现查询分页
使用.NET 6开发TodoList应用(29)——实现静态字符串本地化功能
使用.NET 6开发TodoList应用(27)——实现API的Swagger文档化
使用.NET 6开发TodoList应用(17)——实现数据塑形
使用.NET 6开发TodoList应用(10)——实现DELETE请求以及HTTP请求幂等性
使用.NET 6开发TodoList应用(26)——实现Configuration和Option的强类型绑定
使用.NET 6开发TodoList应用(28)——实现应用程序健康检查

联系我们
联系电话:15090125178(微信同号)
电子邮箱:garson_zhang@163.com
站长微信二维码
微信二维码