.NET Core跨库关联用户ID与档案,替换GUID为用户名
解决「最后编辑人」显示GUID而非用户名的问题
刚好之前处理过类似的场景,结合你用Identity Server 4的情况,给你几个可行的方案,你可以根据自己的架构选型来适配:
方案一:直接在仓储查询中关联OAuth用户表
如果你的应用仓储有权限访问Identity Server的OAuth数据库(比如AspNetUsers表),这是最直接高效的方式。只需要修改查询语句,关联用户表并拼接姓名:
假设你原来的仓储查询是这样的:
SELECT Id, Title, LastEditorId, ... FROM YourBusinessTable
修改为关联用户表,替换GUID为姓名:
SELECT t.Id, t.Title, CONCAT(u.FirstName, ' ', u.LastName) AS LastEditorName, -- 其他业务字段... FROM YourBusinessTable t LEFT JOIN AspNetUsers u ON t.LastEditorId = u.Id
注意:如果你的用户表字段名不是
FirstName/LastName,替换成你实际的字段即可;用LEFT JOIN是为了避免因用户数据缺失导致业务数据不显示。
方案二:通过Identity Server的用户信息API获取姓名
如果仓储无法直接访问OAuth数据库(比如数据库隔离、微服务架构),可以在Web应用中调用Identity Server提供的用户信息接口,或者自己封装一个查询用户信息的API:
步骤1:在Identity Server中配置API权限
首先确保你的Web应用客户端有权限访问用户信息相关的API范围,比如在Identity Server的配置中添加一个user-profile的API资源,并给Web应用客户端分配这个范围的权限。
步骤2:在Web应用中实现查询逻辑
添加一个服务类,负责根据用户GUID获取姓名:
public class UserProfileService : IUserProfileService { private readonly IHttpClientFactory _httpClientFactory; private readonly IConfiguration _configuration; public UserProfileService(IHttpClientFactory httpClientFactory, IConfiguration configuration) { _httpClientFactory = httpClientFactory; _configuration = configuration; } public async Task<string> GetFullNameByIdAsync(string userId) { var client = _httpClientFactory.CreateClient(); // 先获取访问令牌 var tokenRequest = new ClientCredentialsTokenRequest { Address = _configuration["IdentityServer:TokenEndpoint"], ClientId = _configuration["IdentityServer:ClientId"], ClientSecret = _configuration["IdentityServer:ClientSecret"], Scope = "user-profile" }; var tokenResponse = await client.RequestClientCredentialsTokenAsync(tokenRequest); if (tokenResponse.IsError) throw new InvalidOperationException($"Failed to get token: {tokenResponse.Error}"); // 调用用户信息API client.SetBearerToken(tokenResponse.AccessToken); var userInfo = await client.GetFromJsonAsync<UserInfo>($"{_configuration["IdentityServer:ApiEndpoint"]}/users/{userId}"); return userInfo != null ? $"{userInfo.FirstName} {userInfo.LastName}" : userId; // 兜底显示GUID } private class UserInfo { public string FirstName { get; set; } public string LastName { get; set; } } }
然后在你的业务逻辑中,获取到业务数据后,调用这个服务替换LastEditorId为姓名即可。
方案三:添加缓存优化性能
不管用上面哪种方案,用户姓名不会频繁变更,所以建议添加缓存来减少重复查询:
比如用.NET的IMemoryCache实现缓存:
public class CachedUserProfileService : IUserProfileService { private readonly IUserProfileService _innerService; private readonly IMemoryCache _cache; private const string CacheKeyPrefix = "UserFullName_"; private static readonly TimeSpan CacheDuration = TimeSpan.FromHours(1); public CachedUserProfileService(IUserProfileService innerService, IMemoryCache cache) { _innerService = innerService; _cache = cache; } public async Task<string> GetFullNameByIdAsync(string userId) { var cacheKey = $"{CacheKeyPrefix}{userId}"; if (_cache.TryGetValue(cacheKey, out string fullName)) return fullName; fullName = await _innerService.GetFullNameByIdAsync(userId); _cache.Set(cacheKey, fullName, CacheDuration); return fullName; } }
这样可以避免每次请求都去查数据库或者调用API,提升应用性能。
内容的提问来源于stack exchange,提问作者egmfrs
相关产品推荐
相关产品推荐

