Files
dengbolingandClaude Sonnet 4.6 6aca0297bb feat: 网关管理模块 + RBAC权限认证 + 组织架构 + 审计日志
- 网关管理:GatewayEntity/Service/Controller CRUD + 测试连接;设备 GatewayId 外键关联
- JWT 认证:登录签发 Token(权限编码写入 Claims)、RequirePermission 权限过滤器、CurrentUser 上下文
- RBAC:用户/角色/权限实体与 CRUD,预定义 4 角色 + 6 权限种子(admin/admin123)
- 组织架构:sys_org 固定层级树(公司/实验室/部门/班组白夜班),层级校验,用户挂 OrgId/岗位/技能标签
- 数据权限:角色 DataScope(全部/本组织及下级),用户列表按组织子树过滤
- 防锁死保护:禁止删/禁自己,保证至少一名活跃管理员,角色摘除 user:manage 前校验
- 审计日志:AuditRecorder 接入设备增删改/指令下发/登录登出/组织变更,AuditController 查询
- 设备指令下发按网关表取连接参数;设备列表支持 gatewayId/productId 筛选

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-10 17:31:39 +08:00

50 lines
1.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Security.Cryptography;
using System.Text;
namespace Service.Implement
{
/// <summary>
/// 密码哈希工具(PBKDF2-SHA256,格式 salt$hash,盐随机 16 字节)
/// </summary>
public static class PasswordHelper
{
private const int Iterations = 10_000;
private const int SaltSize = 16;
private const int HashSize = 32;
/// <summary>生成密码哈希(salt$hash</summary>
public static string Hash(string password)
{
var salt = RandomNumberGenerator.GetBytes(SaltSize);
var hash = Rfc2898DeriveBytes.Pbkdf2(password, salt, Iterations, HashAlgorithmName.SHA256, HashSize);
return $"{Convert.ToHexString(salt)}${Convert.ToHexString(hash)}";
}
/// <summary>校验密码是否匹配</summary>
public static bool Verify(string password, string? stored)
{
if (string.IsNullOrWhiteSpace(stored)) return false;
var parts = stored.Split('$');
if (parts.Length != 2) return false;
var salt = Convert.FromHexString(parts[0]);
var expected = Convert.FromHexString(parts[1]);
var actual = Rfc2898DeriveBytes.Pbkdf2(password, salt, Iterations, HashAlgorithmName.SHA256, expected.Length);
return CryptographicOperations.FixedTimeEquals(actual, expected);
}
/// <summary>生成随机盐字符串(供外部使用)</summary>
public static string NewSalt()
{
var salt = RandomNumberGenerator.GetBytes(SaltSize);
return Convert.ToHexString(salt).ToLowerInvariant();
}
/// <summary>SHA256(供 RefreshToken 等场景)</summary>
public static string Sha256(string input)
{
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input));
return Convert.ToHexString(bytes).ToLowerInvariant();
}
}
}