diff --git a/src/Infrastructure/HttpUserContext/ClaimConstants.cs b/src/Infrastructure/HttpUserContext/ClaimConstants.cs
new file mode 100644
index 0000000..4704fc0
--- /dev/null
+++ b/src/Infrastructure/HttpUserContext/ClaimConstants.cs
@@ -0,0 +1,8 @@
+namespace Infrastructure.HttpUserContext;
+
+public static class ClaimConstants
+{
+ public const string RoleId = "role_id";
+
+ public const string PermissionCode = "permission_code";
+}
\ No newline at end of file
diff --git a/src/Infrastructure/HttpUserContext/IUserContext.cs b/src/Infrastructure/HttpUserContext/IUserContext.cs
index 5adcb82..18d52c9 100644
--- a/src/Infrastructure/HttpUserContext/IUserContext.cs
+++ b/src/Infrastructure/HttpUserContext/IUserContext.cs
@@ -1,4 +1,5 @@
using System.Security.Claims;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
namespace Infrastructure.HttpUserContext;
@@ -6,50 +7,62 @@ namespace Infrastructure.HttpUserContext;
/// 用户上下文
///
///
-public interface IUserContext where TId : IEquatable
+public interface IUserContext where TId : IEquatable
{
///
/// 用户primary key的类型
///
- TId Id { get; }
+ TId Id { get; set; }
///
/// 用户名
///
- string Username { get; }
+ string Username { get; set; }
///
/// 名称
///
- string Name { get; }
+ string Name { get; set; }
///
/// 邮箱
///
- string Email { get; }
+ string Email { get; set; }
///
/// 角色id
///
- string[] RoleIds { get; }
+ string[] RoleIds { get; set; }
+
+ ///
+ /// 角色名称
+ ///
+ string[] RoleNames { get; set; }
+
+ ///
+ /// 权限
+ ///
+ string[] Permissions { get; set; }
///
/// 访问Ip
///
- string RemoteIpAddress { get; }
+ string RemoteIpAddress { get; set; }
///
/// 生成Jwt token信息
///
- ///
+ ///
///
///
///
- JwtTokenInfo GenerateTokenInfo(JwtSecurityToken jwtSecurityToken, double? duration, string schemeName);
+ JwtTokenInfo GenerateTokenInfo(IList? claims = null,
+ double? duration = null,
+ string schemeName = JwtBearerDefaults.AuthenticationScheme);
///
/// 从当前用户上下文获取claims
///
///
- IList GetClaimsFromUserContext();
+ IList? GetClaimsFromUserContext(bool includePermissions = false);
}
\ No newline at end of file
diff --git a/src/Infrastructure/HttpUserContext/UserContext.cs b/src/Infrastructure/HttpUserContext/UserContext.cs
index cea4deb..2a8837c 100644
--- a/src/Infrastructure/HttpUserContext/UserContext.cs
+++ b/src/Infrastructure/HttpUserContext/UserContext.cs
@@ -24,25 +24,84 @@ public class UserContext(
{
private readonly ClaimsPrincipal principal = httpContextAccessor?.HttpContext?.User;
- public TId Id => GetIdFromClaims();
+ private TId? _id;
- public string Username => principal.Claims.First(c => c.Type == JwtRegisteredClaimNames.UniqueName).Value;
+ private string? _username;
- public string Name => principal.Claims.First(c => c.Type == JwtRegisteredClaimNames.Name).Value;
+ private string? _name;
- public string Email => principal.Claims.First(c => c.Type == JwtRegisteredClaimNames.Email).Value;
+ private string? _email;
- public string[] RoleIds => principal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray();
+ private string[]? _roleIds;
- public string RemoteIpAddress => httpContextAccessor.HttpContext?.GetRequestIp()!;
+ private string? _remoteIpAddress;
+
+ private string[]? _roleNames;
+
+ private string[]? _permissions;
+
+ public TId Id
+ {
+ get => _id ??= GetIdFromClaims();
+ set => _id = value;
+ }
+
+ public string Username
+ {
+ get => _username ??= principal.Claims.First(c => c.Type == JwtRegisteredClaimNames.UniqueName).Value;
+ set => _username = value;
+ }
+
+ public string Name
+ {
+ get => _name ??= principal.Claims.First(c => c.Type == JwtRegisteredClaimNames.Name).Value;
+ set => _name = value;
+ }
+
+ public string Email
+ {
+ get => _email ??= principal.Claims.First(c => c.Type == JwtRegisteredClaimNames.Email).Value;
+ set => _email = value;
+ }
+
+ public string[] RoleIds
+ {
+ get => _roleIds ??= principal.Claims.Where(c => c.Type == ClaimConstants.RoleId).Select(c => c.Value).ToArray();
+ set => _roleIds = value;
+ }
+
+ public string[] RoleNames
+ {
+ get => _roleNames ??= principal.Claims.Where(c => c.Type == ClaimTypes.Role)
+ .Select(c => c.Value).ToArray();
+ set => _roleNames = value;
+ }
+
+ public string[] Permissions
+ {
+ get => _permissions ??= principal.Claims.Where(c => c.Type == ClaimConstants.PermissionCode)
+ .Select(c => c.Value).ToArray();
+ set => _permissions = value;
+ }
+
+ public string RemoteIpAddress
+ {
+ get => _remoteIpAddress ??= httpContextAccessor.HttpContext?.GetRequestIp()!;
+ set => _remoteIpAddress = value;
+ }
public JwtTokenInfo GenerateTokenInfo(
- JwtSecurityToken? securityToken = null,
+ IList? claims = null,
double? duration = null,
string schemeName = JwtBearerDefaults.AuthenticationScheme)
{
- var claims = GetClaimsFromUserContext();
- securityToken ??= new JwtSecurityToken(
+ claims ??= GetClaimsFromUserContext();
+ if (double.NaN == duration)
+ {
+ duration = jwtContext.Duration;
+ }
+
+ var securityToken = new JwtSecurityToken(
issuer: jwtContext.Issuer,
audience: jwtContext.Audience,
claims: claims,
@@ -51,10 +110,10 @@ public class UserContext(
signingCredentials: jwtContext.SigningCredentials);
var token = jwtSecurityTokenHandler.WriteToken(securityToken);
token = encryptionService.Encrypt(token);
- return new JwtTokenInfo(token, duration ?? jwtContext.Duration, schemeName);
+ return new JwtTokenInfo(token, duration.Value, schemeName);
}
- public IList GetClaimsFromUserContext()
+ public IList? GetClaimsFromUserContext(bool includePermissions = false)
{
var claims = new List()
{
@@ -68,7 +127,13 @@ public class UserContext(
new(JwtRegisteredClaimNames.Exp,
TimeSpan.FromSeconds(jwtContext.Duration).ToString())
};
- claims.AddRange(RoleIds.Select(rId => new Claim(ClaimTypes.Role, rId)));
+ claims.AddRange(RoleIds.Select(rId => new Claim(ClaimConstants.RoleId, rId)));
+ claims.AddRange(RoleNames.Select(rName => new Claim(ClaimTypes.Role, rName)));
+ if (includePermissions)
+ {
+ claims.AddRange(Permissions.Select(p => new Claim(ClaimConstants.PermissionCode, p)));
+ }
+
return claims;
}