一.需求
请求加上Authorization头部,按指定格式添加校验内容。Authorization包含以下几个方面信息:
- 校验方式:固定为HMAC-SHA256
- timestamp:当前时间的13位毫秒时间戳
- signature:请求签名,按指定方式生成
二.实现
final String secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
final String algorithm = "HmacSHA256";
private boolean authorizationValidation(HttpServletRequest request) { CachedBodyHttpServletRequest cachedRequest = (CachedBodyHttpServletRequest) request; String authorizationHeader = request.getHeader("Authorization");try { // 解析 Authorization 值 String[] authValues = authorizationHeader.split(","); String timestamp = authValues[1]; String body = cachedRequest.getBody(); if (body == null) { body = ""; } String receivedSignature = authValues[2]; String path = request.getRequestURI(); String query = request.getQueryString(); if (StringUtils.isNotBlank(query)) { path += "?" + query; } // 构建参与签名的字符串 StringBuilder stringToSign = new StringBuilder(); stringToSign.append(path).append("\n"); stringToSign.append(timestamp).append("\n"); stringToSign.append(body).append("\n");// 使用 HMAC-SHA256 算法进行签名 SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), algorithm); Mac mac = Mac.getInstance(algorithm); mac.init(signingKey); byte[] signatureBytes = mac.doFinal(stringToSign.toString().getBytes(StandardCharsets.UTF_8)); // 对签名进行 Base64 编码 String calculatedSignature = Base64.getEncoder().encodeToString(signatureBytes);// 对比签名值 if (calculatedSignature.equals(receivedSignature)) {return true; } } catch (NoSuchAlgorithmException | InvalidKeyException e) { e.printStackTrace(); log.info(e.getMessage()); } return false; }
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
private final byte[] cachedBody;
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
InputStream requestInputStream = request.getInputStream();
this.cachedBody = StreamUtils.copyToByteArray(requestInputStream);
}
@Override
public ServletInputStream getInputStream() {
return new CachedBodyServletInputStream(this.cachedBody);
}
@Override
public BufferedReader getReader() throws IOException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody);
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
}
public String getBody() {
return new String(cachedBody);
}
}
public abstract class StreamUtils {
public static final int BUFFER_SIZE = 4096;
public StreamUtils() {
}
public static byte[] copyToByteArray(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
copy(in, out);
return out.toByteArray();
}
public static int copy(InputStream in, OutputStream out) throws IOException {
int byteCount = 0;
byte[] buffer = new byte[4096];
int bytesRead;
for(boolean var4 = true; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
out.write(buffer, 0, bytesRead);
}
out.flush();
return byteCount;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?