diff --git a/cjpm.lock b/cjpm.lock index ebeb7c6..a613f18 100644 --- a/cjpm.lock +++ b/cjpm.lock @@ -1,20 +1,20 @@ version = 0 [requires] - soulsoft_extensions_hosting = {version = "1.0.20260528"} soulsoft_web_http = {version = "1.0.20260528"} - soulsoft_extensions_options_configuration = {version = "1.0.20260528"} - soulsoft_extensions_options = {version = "1.0.20260528"} + soulsoft_extensions_hosting = {version = "1.0.20260528"} soulsoft_web_routing = {version = "1.0.20260528"} - soulsoft_serialization = {version = "1.0.20260528"} soulsoft_web_hosting = {version = "1.0.20260528"} - soulsoft_net_http = {version = "1.0.20260528"} soulsoft_web_mvc = {version = "1.0.20260528"} - soulsoft_web_cors = {version = "1.0.20260528"} - redis = {version = "1.0.20260627"} - soulsoft_identity_claims = {version = "1.0.20260528"} - soulsoft_extensions_logging = {version = "1.0.20260528"} - soulsoft_extensions_logging_console = {version = "1.0.20260528"} - soulsoft_extensions_logging_configuration = {version = "1.0.20260528"} - soulsoft_extensions_configuration = {version = "1.0.20260528"} soulsoft_extensions_injection = {version = "1.0.20260528"} + soulsoft_web_cors = {version = "1.0.20260528"} + soulsoft_extensions_options = {version = "1.0.20260528"} + soulsoft_extensions_logging = {version = "1.0.20260528"} + soulsoft_serialization = {version = "1.0.20260528"} + soulsoft_extensions_logging_console = {version = "1.0.20260528"} + soulsoft_net_http = {version = "1.0.20260528"} + soulsoft_extensions_logging_configuration = {version = "1.0.20260528"} + soulsoft_identity_claims = {version = "1.0.20260528"} + soulsoft_extensions_options_configuration = {version = "1.0.20260528"} + redis = {version = "1.0.20260627"} + soulsoft_extensions_configuration = {version = "1.0.20260528"} diff --git a/src/helpers/SimApiAesBodyChecker.cj b/src/helpers/SimApiAesBodyChecker.cj index 9508a7f..9c4a74e 100644 --- a/src/helpers/SimApiAesBodyChecker.cj +++ b/src/helpers/SimApiAesBodyChecker.cj @@ -11,6 +11,7 @@ import simapi_serialization.* import soulsoft_web_http.* import simapi.communications.* import simapi.exceptions.* +import simapi.interfaces.* /** * AES body 请求({"data": "密文"},对齐 C# SimApiOneFieldRequest)。 @@ -21,32 +22,13 @@ public class AesBodyRequest { public init() {} } -/** - * AES body 密钥提供器(对齐 C# ModelBinders/AesBodyProviderBase): - * 应用继承本类并实现 getKey(appId),返回 appId 对应的 AES 密钥。 - */ -public open class AesBodyProviderBase { - /// appId 字段名(None 表示不带 appId) - public var appIdName: ?String = Some("appId") - - public init() {} - - /** - * 根据 appId 获取密钥。 - * @param appId 应用 ID(未配置 appIdName 时为 None)。 - * @return 密钥;返回 None 表示获取失败。 - */ - public open func getKey(appId: ?String): ?String { - None - } -} - /** * 服务端 AES body 解密校验器(对齐 C# ModelBinders/AesBodyModelBinder)。 * * 仓颉无 ModelBinder 机制,按项目惯例由控制器在方法开头调用: * let jsonStr = SimApiAesBodyChecker.decryptBody(context, provider) * let request = JsonSerializer.Deserialize(jsonStr) + * 或标注 @AesBody 注解自动执行(SimApiRequestDelegateFactory)。 * * 流程(与 C# 一致): * 1. 读取 body 并反序列化为 {"data": "密文"} diff --git a/src/helpers/SimApiSignChecker.cj b/src/helpers/SimApiSignChecker.cj index 838bfed..710d7b7 100644 --- a/src/helpers/SimApiSignChecker.cj +++ b/src/helpers/SimApiSignChecker.cj @@ -8,50 +8,14 @@ package simapi.helpers import std.convert.* import soulsoft_web_http.* import simapi.exceptions.* - -/** - * 签名提供器(对齐 C# ModelBinders/SimApiSignProviderBase): - * 应用继承本类并实现 getKey(appId),返回 appId 对应的密钥。 - */ -public open class SimApiSignProviderBase { - /// appId 字段名(None 表示签名中不包含 appId) - public var appIdName: ?String = Some("appId") - - /// 时间戳字段名 - public var timestampName: String = "timestamp" - - /// 随机串字段名 - public var nonceName: String = "nonce" - - /// 签名字段名 - public var signName: String = "sign" - - /// 请求过期秒数(0 表示不校验 timestamp) - public var queryExpires: Int64 = 5 - - /// 是否开启 nonce 去重(需配置缓存) - public var duplicateRequestProtection: Bool = true - - /// 参与签名的额外字段(与 appId/timestamp/nonce 一起拼入签名字符串) - public var signFields: Array = [] - - public init() {} - - /** - * 根据 appId 获取密钥。 - * @param appId 应用 ID(未配置 appIdName 时为 None)。 - * @return 密钥;返回 None 表示获取失败。 - */ - public open func getKey(appId: ?String): ?String { - None - } -} +import simapi.interfaces.* /** * 服务端验签校验器(对齐 C# Attributes/SimApiSignAttribute.OnActionExecuting)。 * * 仓颉无声明式 ActionFilter 机制,按项目惯例(同 requireLogin)由控制器在需要验签的方法开头调用: * SimApiSignChecker.verify(context, provider, cache) + * 或标注 @SimApiSign 注解自动执行(SimApiRequestDelegateFactory)。 * * 校验流程(与 C# 完全一致): * 1. 提取 appId(Query/Header) diff --git a/src/interfaces/AesBodyProviderBase.cj b/src/interfaces/AesBodyProviderBase.cj new file mode 100644 index 0000000..1ca5f3d --- /dev/null +++ b/src/interfaces/AesBodyProviderBase.cj @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 SimcuTeam. All rights reserved. + * 移植自 C# 项目 SimApi(E:\simcu\simapi-net),遵循 MIT 许可证。 + * AES body 密钥提供器基类(对齐 C# ModelBinders/AesBodyProviderBase)。 + * + * 说明:本类含配置字段(appIdName),故用 open class 而非 interface + * (Cangjie 接口不能声明字段),与 .NET 抽象类对应。应用继承本类并实现 getKey。 + */ + +package simapi.interfaces + +/** + * AES body 密钥提供器基类:应用继承并实现 getKey(appId),返回 appId 对应的 AES 密钥。 + */ +public open class AesBodyProviderBase { + /// appId 字段名(None 表示不带 appId) + public var appIdName: ?String = Some("appId") + + public init() {} + + /** + * 根据 appId 获取密钥。 + * @param appId 应用 ID(未配置 appIdName 时为 None)。 + * @return 密钥;返回 None 表示获取失败。 + */ + public open func getKey(appId: ?String): ?String { + None + } +} diff --git a/src/interfaces/SimApiSignProviderBase.cj b/src/interfaces/SimApiSignProviderBase.cj new file mode 100644 index 0000000..2fee710 --- /dev/null +++ b/src/interfaces/SimApiSignProviderBase.cj @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 SimcuTeam. All rights reserved. + * 移植自 C# 项目 SimApi(E:\simcu\simapi-net),遵循 MIT 许可证。 + * 签名提供器基类(对齐 C# ModelBinders/SimApiSignProviderBase)。 + * + * 说明:本类含配置字段(appIdName/queryExpires 等),故用 open class 而非 interface + * (Cangjie 接口不能声明字段),与 .NET 抽象类对应。应用继承本类并实现 getKey。 + */ + +package simapi.interfaces + +/** + * 签名提供器基类:应用继承并实现 getKey(appId),返回 appId 对应的密钥。 + */ +public open class SimApiSignProviderBase { + /// appId 字段名(None 表示签名中不包含 appId) + public var appIdName: ?String = Some("appId") + + /// 时间戳字段名 + public var timestampName: String = "timestamp" + + /// 随机串字段名 + public var nonceName: String = "nonce" + + /// 签名字段名 + public var signName: String = "sign" + + /// 请求过期秒数(0 表示不校验 timestamp) + public var queryExpires: Int64 = 5 + + /// 是否开启 nonce 去重(需配置缓存) + public var duplicateRequestProtection: Bool = true + + /// 参与签名的额外字段(与 appId/timestamp/nonce 一起拼入签名字符串) + public var signFields: Array = [] + + public init() {} + + /** + * 根据 appId 获取密钥。 + * @param appId 应用 ID(未配置 appIdName 时为 None)。 + * @return 密钥;返回 None 表示获取失败。 + */ + public open func getKey(appId: ?String): ?String { + None + } +}