Zongsoft.Security
Zongsoft.Core 中 Zongsoft.Security 命名空间的声明身份、凭证、密钥、验证码与安全基础模型。
Zongsoft.Security 是核心库中的安全基础层。它不直接等同于完整的安全业务模块,而是为上层的 Zongsoft.Security 插件、Web 认证、业务身份模型和权限系统提供可复用的抽象、工具和运行时对象。
核心库把安全能力拆成三类:
权限、认证器、授权器、用户、角色和成员模型位于 Zongsoft.Security.Privileges。如果只想了解权限树、角色继承和授权计算,请直接阅读该页。
设计边界
核心安全命名空间只定义“如何表达身份与安全材料”,不规定“用户表怎么设计”或“登录接口怎么写”。默认数据库、服务实现和插件挂载位于 Zongsoft.Security 项目;业务系统可以继承核心抽象,替换模型、查询条件、claims 补充逻辑和权限存储字段。
这种分层的好处是:
身份载体基于标准
ClaimsIdentity(源码) 和ClaimsPrincipal(源码),可以接入 ASP.NET Core、令牌认证和宿主上下文。业务身份可以通过 转换器 从 Claims 还原成强类型模型,调用方不必到处解析字符串。
凭证、验证码、密码、证书等安全材料以接口暴露,默认实现可替换,业务模块只依赖稳定契约。
声明模型
声明是登录后在进程内传递身份信息的最小单元。一个 Claim 源码 保存一项事实,例如用户编号、用户名、角色、租户编号、语言或授权信息。
ClaimNames 定义了 Zongsoft 额外约定的声明名:
Namespace
身份所属命名空间,常用于多租户、组织或业务域隔离。
Description
身份或声明对象的说明文本。
Creation、Modification
创建和修改时间。
Authorization
授权相关声明,通常作为可重复声明处理。
ClaimUtility 负责 Claim 值与 .NET 类型之间的转换。它根据 Claim 的 ValueType 识别 bool、DateTime 源码、DateOnly 源码、TimeOnly 源码、整数、浮点数、TimeSpan 源码 或 Zongsoft 类型别名。设置 Claim 时,ClaimsIdentityExtension.SetClaim(...) 会反向生成合适的 ValueType。
来源:src/Security/UserChallenger.cs(节选;上下文见源文件)。
ClaimsIdentityExtension 还提供了常用读取和判断:
GetIdentifier<T>()读取ClaimTypes.NameIdentifier并转换成指定类型。GetNamespace()/SetNamespace(...)处理 Zongsoft 命名空间声明。InRole(...)、InRoles(...)和IsAdministrator()按身份中的角色声明判断。GetQualifiedName()组合命名空间与名称,形成namespace:name风格的限定名。AsModel<T>()把 Claims 写入IUser、IModel或普通对象。
凭证主体
CredentialIdentity 是登录身份,构造时会写入名称声明和签发者声明。签发者使用 ClaimTypes.System 保存,因此同一个 ClaimsPrincipal 源码 可以按认证方案或模块查找对应身份。
CredentialPrincipal 是登录后的凭证主体,扩展了标准 ClaimsPrincipal 源码:
CredentialId
凭证编号,用于注册、查找、注销和模型缓存键。
RenewalToken
续约令牌,用于刷新凭证或延长会话。
Scenario
登录场景,例如 web、api、mobile。
Validity
凭证有效时长。
Disposed
凭证失效通知,身份模型缓存会随之失效。
CredentialPrincipal 可以序列化和反序列化,因此默认凭证提供器可以把它写入缓存、Cookie 或其他存储。认证成功后,Authentication.AuthenticateAsync(...) 会创建凭证主体,执行 质询器(Challengers),最后通过 ICredentialProvider.RegisterAsync(...) 注册。
身份模型转换
ClaimsIdentityModeling 是当前推荐的身份模型入口。它从 ApplicationContext.Current.Principal 或传入的 主体 中获取 CredentialPrincipal,再按认证方案取出对应身份并执行转换。
转换器有两种来源:
Authentication.Transformer中的ClaimsPrincipalTransformer.Transformers。当前应用服务容器中的
IClaimsIdentityTransformer。
转换结果会以 CredentialId 和 scheme 为键缓存;凭证主体释放时缓存随之失效。Discussions 的 UserIdentity.Current 按 Zongsoft.Discussions 方案读取模型:
来源:src/Security/UserIdentity.cs(节选;上下文见源文件)。
业务 转换器 通常只处理自己认识的认证方案,把 Claim 转成业务身份属性:
来源:src/Security/UserIdentity.cs(节选;上下文见源文件)。
密码与秘密
Password 是核心库推荐的密码摘要结构。它把算法、指数、随机数和派生值打包在同一个值中,文本格式类似:
算法#指数:随机数|派生值。这是格式说明,真实序列化与验证输入见 PasswordTest。
Password.Generate(...) 使用 PBKDF2 生成摘要;省略算法参数时默认使用 SHA256。Verify(...) 根据摘要中保存的算法、随机数和指数重新计算,因此已有 SHA1 摘要仍可继续验证。旧的 PasswordUtility 已标记为过时,新的实现应优先使用 Password;业务服务中的 Passworder 目前仍保留旧格式兼容路径,后续需要配合重哈希迁移。
ISecretor 和 Secretor 用于一次性秘密,例如短信验证码、邮箱验证码、找回密码令牌或敏感操作二次确认。默认实现把秘密保存到分布式缓存,支持:
GenerateAsync(...)
按名称生成秘密,并保存附加文本。
VerifyAsync(...)
校验秘密但不删除,适合有效期内可重复确认的场景。
RemoveAsync(...)
校验成功后删除,适合一次性消费。
Period
限制同一名称重复生成的最小间隔。
Transmitter
发送秘密,可接入短信、邮件、站内信和验证码校验。
证书、签名与挑战
ICertificate、ICertificateProvider<TCertificate>、ICertificateResolver 和 Certificate 封装证书标识、颁发者、主体、有效期以及 RSA/X509 证书适配。ISignaturer 和 ISecretor 分别覆盖签名与秘密校验场景。
IChallenger 是认证后的补充质询点。认证器只负责“凭据是否正确”和“签发基础身份”,challenger 负责登录后的业务检查与 claims 增强。Discussions 的 UserChallenger 完成以下工作:
从主身份读取用户编号,并查询或创建 Discussions 用户资料。
创建资料时从身份命名空间确定 SiteId;已有资料保留自己的站点信息。
调用 OnVerify 扩展点,再创建 Zongsoft.Discussions 身份加入主体。
写入 SiteId、Gender、Avatar、Grade、TotalPosts 和 TotalThreads 声明。
当前 OnVerify 是空实现,不能据此宣称已校验账号启用状态、站点状态或许可范围;这些业务准入规则需要由实际模块补充。资料统计声明也是签发时的快照,不会随每次发帖自动刷新。
这种拆分能让密码登录、验证码登录等不同认证方式共享同一组业务质询规则。
异常与原因
所有安全相关异常都继承自 SecurityException。SecurityReasons 提供稳定原因码,例如:
InvalidIdentity
身份不存在、编号无效或无法签发身份。
InvalidPassword
密码错误。
AccountDisabled、AccountSuspended
账号不可用或尝试次数过多。
Forbidden
认证通过后不满足业务准入条件。
VerifyFaild
验证码或秘密校验失败。
业务代码应优先抛出带原因码的 AuthenticationException 或 AuthorizationException,便于 Web 层、日志、监控和前端统一处理。
相关页面
最后更新于