using Microsoft.AspNetCore.Http;
|
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.Logging;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.IdentityModel.Tokens.Jwt;
|
using System.Linq;
|
using System.Security.Claims;
|
using System.Text;
|
using System.Threading.Tasks;
|
using WIDESEA_Core.Authorization;
|
using WIDESEA_Core.Const;
|
using WIDESEA_Core.DB;
|
using WIDESEA_Core.Extensions;
|
using WIDESEA_Core.Helper;
|
using WIDESEA_Core.Seed;
|
using ICacheService = WIDESEA_Core.Caches.ICacheService;
|
|
namespace WIDESEA_Core.HttpContextUser
|
{
|
/// <summary>
|
/// 提供基于ASP.NET Core HttpContext的用户信息访问服务
|
/// </summary>
|
/// <remarks>
|
/// 实现IUser接口,通过JWT Token解析用户身份信息,
|
/// 包括用户名、用户ID、租户ID、角色ID等核心属性,
|
/// 并提供Token管理、身份验证和声明信息获取等功能
|
/// </remarks>
|
public class AspNetUser : IUser
|
{
|
private readonly IHttpContextAccessor _accessor;
|
private readonly ICacheService _cacheService;
|
//private readonly ILogger<AspNetUser> _logger;
|
|
public AspNetUser(IHttpContextAccessor accessor, ICacheService cacheService)
|
{
|
_accessor = accessor;
|
_cacheService = cacheService;
|
/*_logger = logger;*/
|
}
|
|
/// <summary>
|
/// 获取当前用户的用户名(从JWT Token中解析)
|
/// </summary>
|
/// <returns>用户名字符串,若不存在则返回空字符串</returns>
|
public string UserName => GetUserInfoFromToken(ClaimTypes.Name).FirstOrDefault() ?? "";
|
|
/// <summary>
|
/// 获取当前用户的ID,从JWT令牌的JTI声明中解析。若声明不存在或解析失败则返回0。
|
/// </summary>
|
/// <returns>用户ID(整数)</returns>
|
public int UserId => GetClaimValueByType(JwtRegisteredClaimNames.Jti) == null ? 0 : GetClaimValueByType(JwtRegisteredClaimNames.Jti).FirstOrDefault()?.ObjToInt() ?? 0;
|
|
/// <summary>
|
/// 从用户令牌中获取租户ID
|
/// </summary>
|
/// <returns>当前用户的租户ID,若获取失败则返回-1</returns>
|
public long TenantId => GetUserInfoFromToken(nameof(TenantId)).FirstOrDefault()?.ObjToLong() ?? -1;
|
|
/// <summary>
|
/// 获取当前用户角色ID(从Token中解析)
|
/// </summary>
|
/// <returns>角色ID,若不存在则返回0</returns>
|
public int RoleId => GetUserInfoFromToken(ClaimTypes.Role).FirstOrDefault()?.ObjToInt() ?? 0;
|
|
/// <summary>
|
/// 获取当前用户的Token
|
/// </summary>
|
public string Token => GetToken();
|
|
/// <summary>
|
/// 获取菜单类型,根据请求头中是否包含"uniapp"标识返回1或0
|
/// </summary>
|
public int MenuType => (_accessor.HttpContext?.Request.Headers.ContainsKey("uniapp") ?? false) ? 1 : 0;
|
|
/// <summary>
|
/// 检查当前HTTP上下文用户是否已认证
|
/// </summary>
|
/// <returns>如果用户已认证返回true,否则返回false</returns>
|
public bool IsAuthenticated()
|
{
|
return _accessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;
|
}
|
|
/// <summary>
|
/// 获取当前用户的JWT Token
|
/// </summary>
|
/// <returns>
|
/// 返回当前请求的Authorization头中的Bearer Token,
|
/// 如果请求来自Swagger且验证成功则返回Swagger的JWT Token,
|
/// 否则尝试从缓存中获取用户Token
|
/// </returns>
|
/// <remarks>
|
/// 1. 优先从请求头Authorization中获取Bearer Token
|
/// 2. 如果是Swagger请求且验证成功,使用Swagger的JWT Token
|
/// 3. 最后尝试从缓存中获取用户Token
|
/// </remarks>
|
public string GetToken()
|
{
|
string token = _accessor.HttpContext?.Request?.Headers["Authorization"].ObjToString().Replace("Bearer ", "") ?? "";
|
if (!token.IsNullOrEmpty())
|
{
|
return token;
|
}
|
if (_accessor.HttpContext?.IsSuccessSwagger() == true)
|
{
|
token = _accessor.HttpContext.GetSuccessSwaggerJwt();
|
if (token.IsNotEmptyOrNull())
|
{
|
//UserInfo userInfo = JwtHelper.SerializeJwt(token);
|
//if (userInfo.UserId > 0)
|
//{
|
// return token;
|
//}
|
List<Claim> claims1 = _accessor.HttpContext.User.Claims.ToList();
|
if (_accessor.HttpContext.User.Claims.Any(s => s.Type == JwtRegisteredClaimNames.Jti))
|
{
|
return token;
|
}
|
|
var claims = new ClaimsIdentity(GetClaimsIdentity(token));
|
_accessor.HttpContext.User.AddIdentity(claims);
|
return token;
|
}
|
}
|
token = _cacheService.Get(UserId.ToString());
|
if (!string.IsNullOrEmpty(token)) { return token; }
|
return token;
|
|
// string token = _cacheService.Get(UserId.ToString());
|
//if (!string.IsNullOrEmpty(token)) { return token; }
|
//return string.Empty;
|
//return _accessor.HttpContext?.Request?.Headers["Authorization"].ObjToString().Replace("Bearer ", "") ?? "";
|
}
|
|
/// <summary>
|
/// 更新用户令牌
|
/// </summary>
|
/// <param name="token">新的令牌字符串</param>
|
/// <remarks>
|
/// 该方法会将用户ID与令牌关联存储到缓存服务中
|
/// </remarks>
|
public void UpdateToke(string token)
|
{
|
_cacheService.AddOrUpdate(UserId.ToString(), token);
|
}
|
|
/// <summary>
|
/// 获取一个值,指示当前用户是否为超级管理员
|
/// </summary>
|
/// <remarks>
|
/// 通过检查角色ID是否为超级管理员角色来判断
|
/// </remarks>
|
public bool IsSuperAdmin => IsRoleIdSuperAdmin(RoleId);
|
|
/// <summary>
|
/// 从JWT令牌中获取指定类型的用户声明信息
|
/// </summary>
|
/// <param name="ClaimType">要获取的声明类型</param>
|
/// <returns>包含声明值的字符串列表,若令牌无效或未找到声明则返回空列表</returns>
|
public List<string> GetUserInfoFromToken(string ClaimType)
|
{
|
var jwtHandler = new JwtSecurityTokenHandler();
|
var token = "";
|
|
token = GetToken();
|
// token校验
|
if (token.IsNotEmptyOrNull() && jwtHandler.CanReadToken(token))
|
{
|
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(token);
|
|
List<string> items = (from item in jwtToken.Claims
|
where item.Type == ClaimType
|
select item.Value).ToList();
|
return items;
|
}
|
|
return new List<string>() { };
|
}
|
|
/// <summary>
|
/// 获取当前HTTP上下文的身份声明集合,包括请求头信息
|
/// </summary>
|
/// <returns>包含当前用户声明和请求头信息的集合,若HttpContext为空则返回空集合</returns>
|
public IEnumerable<Claim> GetClaimsIdentity()
|
{
|
if (_accessor.HttpContext != null)
|
{
|
var claims = _accessor.HttpContext.User.Claims.ToList();
|
var headers = _accessor.HttpContext.Request.Headers;
|
foreach (var header in headers)
|
{
|
claims.Add(new Claim(header.Key, header.Value));
|
}
|
|
return claims;
|
}
|
return ArraySegment<Claim>.Empty;
|
}
|
|
/// <summary>
|
/// 从JWT令牌中获取身份声明(Claims)
|
/// </summary>
|
/// <param name="token">JWT令牌字符串</param>
|
/// <returns>包含声明信息的集合,若令牌无效则返回空集合</returns>
|
public IEnumerable<Claim> GetClaimsIdentity(string token)
|
{
|
var jwtHandler = new JwtSecurityTokenHandler();
|
// token校验
|
if (token.IsNotEmptyOrNull() && jwtHandler.CanReadToken(token))
|
{
|
var jwtToken = jwtHandler.ReadJwtToken(token);
|
|
return jwtToken.Claims;
|
}
|
|
return new List<Claim>();
|
}
|
|
/// <summary>
|
/// 根据声明类型获取对应的声明值列表
|
/// </summary>
|
/// <param name="ClaimType">要查询的声明类型</param>
|
/// <returns>匹配指定类型的声明值列表</returns>
|
public List<string> GetClaimValueByType(string ClaimType)
|
{
|
return (from item in GetClaimsIdentity()
|
where item.Type == ClaimType
|
select item.Value).ToList();
|
}
|
|
/// <summary>
|
/// 检查角色ID是否为超级管理员
|
/// </summary>
|
/// <param name="roleId">要检查的角色ID</param>
|
/// <returns>如果是超级管理员返回true,否则返回false</returns>
|
public bool IsRoleIdSuperAdmin(int roleId)
|
{
|
return roleId == 1;
|
}
|
}
|
|
/// <summary>
|
/// 用户信息实体类
|
/// </summary>
|
/// <remarks>
|
/// 包含用户的基本信息,如租户ID、角色ID、用户名等
|
/// </remarks>
|
public class UserInfo
|
{
|
/// <summary>
|
/// 获取或设置租户ID
|
/// </summary>
|
public long TenantId { get; set; }
|
|
/// <summary>
|
/// 获取或设置用户角色ID
|
/// </summary>
|
public int RoleId { get; set; }
|
|
/// <summary>
|
/// 获取或设置用户的名称
|
/// </summary>
|
public string UserName { get; set; }
|
|
/// <summary>
|
/// 获取或设置用户ID
|
/// </summary>
|
public int UserId { get; set; }
|
|
/// <summary>
|
/// 获取或设置用户的真实姓名
|
/// </summary>
|
public string UserTrueName { get; set; }
|
|
/// <summary>
|
/// 获取或设置用户头像的URL
|
/// </summary>
|
public string HeadImageUrl { get; set; }
|
}
|
}
|