refactor: PSK 签名改为 METHOD:path:timestamp 格式
- 签名内容不再包含 email,email 仅作审计 - 改用 METHOD:path:timestamp 防重放到不同端点 - X-Email 头改为可选 - medibot 签名: HMAC(PSK, 'POST:/api/v1/sites/x/submit:1234567890')
This commit is contained in:
@@ -106,7 +106,8 @@ public class AuthController {
|
|||||||
String sig = request.getHeader("X-Medibot-Signature");
|
String sig = request.getHeader("X-Medibot-Signature");
|
||||||
if (ts == null || sig == null) return false;
|
if (ts == null || sig == null) return false;
|
||||||
try {
|
try {
|
||||||
return pskService.verify(email, Long.parseLong(ts), sig) != null;
|
return pskService.verify(request.getMethod(), request.getRequestURI(),
|
||||||
|
Long.parseLong(ts), sig) != null;
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ public class HmacAuthInterceptor implements HandlerInterceptor {
|
|||||||
// 方式 2:PSK 签名
|
// 方式 2:PSK 签名
|
||||||
String sig = request.getHeader(HEADER_SIGNATURE);
|
String sig = request.getHeader(HEADER_SIGNATURE);
|
||||||
String ts = request.getHeader(HEADER_TIMESTAMP);
|
String ts = request.getHeader(HEADER_TIMESTAMP);
|
||||||
String email = request.getHeader(HEADER_EMAIL);
|
if (sig != null && ts != null) {
|
||||||
if (sig != null && ts != null && email != null) {
|
|
||||||
try {
|
try {
|
||||||
if (pskService.verify(email, Long.parseLong(ts), sig) != null) {
|
if (pskService.verify(request.getMethod(), request.getRequestURI(),
|
||||||
|
Long.parseLong(ts), sig) != null) {
|
||||||
request.setAttribute("accountId", 0L);
|
request.setAttribute("accountId", 0L);
|
||||||
request.setAttribute("trustLevel", com.par.core.enums.TrustLevel.TRUSTED);
|
request.setAttribute("trustLevel", com.par.core.enums.TrustLevel.TRUSTED);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -84,16 +84,15 @@ public class PskService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用所有活跃 PSK 逐一验证签名
|
* 使用所有活跃 PSK 逐一验证签名
|
||||||
* signContent = email + ":" + timestamp
|
* signContent = METHOD:path:timestamp
|
||||||
* @return 匹配的 PSK 版本号,null 表示验证失败
|
* @return "ok" 表示验证通过,null 表示失败
|
||||||
*/
|
*/
|
||||||
public String verify(String email, long timestamp, String signature) {
|
public String verify(String method, String path, long timestamp, String signature) {
|
||||||
long now = System.currentTimeMillis() / 1000;
|
long now = System.currentTimeMillis() / 1000;
|
||||||
if (Math.abs(now - timestamp) > 300) return null; // 5 分钟窗口
|
if (Math.abs(now - timestamp) > 300) return null; // 5 分钟窗口
|
||||||
String payload = email.toLowerCase().trim() + ":" + timestamp;
|
String payload = method.toUpperCase() + ":" + path + ":" + timestamp;
|
||||||
|
|
||||||
String[] secrets = getActiveSecrets();
|
for (String secret : getActiveSecrets()) {
|
||||||
for (String secret : secrets) {
|
|
||||||
if (HmacUtil.verify(secret, payload, signature)) {
|
if (HmacUtil.verify(secret, payload, signature)) {
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user