开放接口签名认证
采用抽象责任链模式实现开放接口的多步骤签名认证流程。通过将认证过程拆分为多个独立处理阶段,每个阶段职责单一,支持灵活扩展与维护。
一、责任链基础抽象
BaseVerifyHandle
抽象类
- 定义了责任链中处理器的统一基类。
- 使用
nextHandle
属性维护链式结构,通过setNextHandle()
方法实现处理器串联。 - 提供
handleRequest(SignatureContext context)
抽象方法,由子类实现具体逻辑。 - 提供
next(context)
工具方法,用于触发链中下一个处理器,简化调用逻辑。
关键特性:
- 支持链式调用,解耦处理逻辑与流程控制。
@Setter
注解自动生成setNextHandle
方法,便于链的组装。
二、具体处理器实现
所有处理器均继承自 BaseVerifyHandle
,按职责划分如下:
1. ParameterHandle
(参数预处理)
- 职责:解析并规范化签名所需参数,如参数提取、排序、过滤等。
- 后续节点:交由签名处理器进行本地签名生成。
2. SignatureHandle
(本地签名生成)
- 依赖:
apiClientsService
,redisCache
,redisson
- 职责:
- 获取客户端密钥信息;
- 解密客户端传输的安全数据;
- 拼接标准签名字符串;
- 执行本地签名算法(如 HMAC-SHA256)。
- 后续节点:进入验证阶段。
3. VerifyHandle
(签名验证)
- 职责:
- 验证时间戳合法性(防重放攻击);
- 比对客户端签名与本地签名;
- 校验客户端身份信息完整性;
- 检查客户端状态(是否禁用等)。
- 后续节点:进入权限校验。
4. PermissionHandle
(权限校验)
依赖:
apiActionsService
职责:
- 查询请求动作(action)的访问控制策略;
- 判断当前接口是否支持匿名访问;
- 验证客户端(App)是否具备执行该操作的权限。
三、责任链组装逻辑
在 verifySignature
方法中完成责任链的动态构建与执行:
组装顺序
ParameterHandle
→SignatureHandle
→VerifyHandle
→PermissionHandle
执行流程
- 构建
SignatureContext
上下文对象,封装请求动作与 HTTP 请求。 - 逐级设置
nextHandle
,形成完整处理链条。 - 从首节点
parameterHandle
触发handleRequest
,流程自动向后传递。
抽象责任链
java
@Setter
public abstract class BaseVerifyHandle {
/**
* -- SETTER --
* 设置下一个处理器
*
* @param nextHandle 下一个处理器
*/
protected BaseVerifyHandle nextHandle;
/**
* 处理请求
* @param context 签名上下文
* @return
*/
public abstract void handleRequest(SignatureContext context);
// 进行签名
public void next(SignatureContext context) {
if (nextHandle != null) {
nextHandle.handleRequest(context);
}
}
}
责任链具体实现
java
@Slf4j
@AllArgsConstructor
public class ParameterHandle extends BaseVerifyHandle {
/**
* 处理请求
*
* @param context 签名上下文
* @return
*/
@Override
public void handleRequest(SignatureContext context) {
// ... 签名参数解析 排序等等操作
next(context);
}
}
java
@AllArgsConstructor
@Slf4j
public class PermissionHandle extends BaseVerifyHandle {
@Override
public void handleRequest(SignatureContext context) {
// ...获取请求动作详情 是否支持匿名 检查app客户端是否有该权限
next(context);
}
}
java
@Slf4j
@AllArgsConstructor
public class SignatureHandle extends BaseVerifyHandle {
/**
* 处理请求
*
* @param context 签名上下文
* @return
*/
@Override
public void handleRequest(SignatureContext context) {
//... 进行本地签名 拼接签名参数 读取app客户端信息 解密客户端信息 本地签名
next(context);
}
}
java
@Slf4j
public class VerifyHandle extends BaseVerifyHandle {
@Override
public void handleRequest(SignatureContext context) {
// 时间戳验证 签名比对 校验客户端信息 客户端状态
next(context);
}
}
责任链组装
java
/**
* 验证签名
*
* @param action 请求动作
* @param currentHttpRequest
*/
private void verifySignature(String action, HttpServletRequest currentHttpRequest) {
// 初始化签名参数对象
SignatureContext context = new SignatureContext();
// 设置请求动作
context.setAction(action);
context.setRequest(currentHttpRequest);
// 责任链验证 参数初始化操作
ParameterHandle parameterHandle = new ParameterHandle();
// 签名操作
SignatureHandle signatureHandle = new SignatureHandle(apiClientsService, redisCache, redisson);
parameterHandle.setNextHandle(signatureHandle);
// 验证操作
VerifyHandle verifyHandle = new VerifyHandle();
signatureHandle.setNextHandle(verifyHandle);
// 权限操作
PermissionHandle permissionHandle = new PermissionHandle(apiActionsService);
verifyHandle.setNextHandle(permissionHandle);
// 执行责任链
parameterHandle.handleRequest(context);
}