日常事务-处分管理 添加印章图片签名验证功能
- 实现了图片签名工具类ImageSignUtils,支持生成和验证带时间戳的签名URL - 配置SecurityConfig允许匿名访问签名的印章图片URL,但Base64接口需认证 - 创建StampController提供受保护的印章图片访问接口 - 将应用默认文件路径配置改为Windows环境路径 - 支持通过签名URL安全访问印章图片资源
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package com.srs.common.utils.sign;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 图片签名工具类
|
||||
* 用于生成和验证图片访问签名URL
|
||||
*/
|
||||
public class ImageSignUtils {
|
||||
|
||||
private static final String SECRET_KEY = "srs-stamp-secret-key-2024";
|
||||
private static final long DEFAULT_EXPIRE_TIME = 3 * 60_000; // 3分钟
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
*/
|
||||
public static String generateSign(String fileName, long expireTime) {
|
||||
String raw = fileName + "-" + expireTime + "-" + SECRET_KEY;
|
||||
return md5(raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成带签名的URL
|
||||
*/
|
||||
public static String generateSignedUrl(String fileName) {
|
||||
long expireTime = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME;
|
||||
String sign = generateSign(fileName, expireTime);
|
||||
return String.format("/common/stamp/%s?expire=%d&sign=%s",
|
||||
encodeFileName(fileName), expireTime, sign);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证签名是否有效
|
||||
*/
|
||||
public static boolean validateSign(String fileName, long expireTime, String sign) {
|
||||
if (System.currentTimeMillis() > expireTime) {
|
||||
return false; // 已过期
|
||||
}
|
||||
String expectedSign = generateSign(fileName, expireTime);
|
||||
return expectedSign.equals(sign);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从请求中提取文件名
|
||||
*/
|
||||
public static String extractFileName(HttpServletRequest request) {
|
||||
String uri = request.getRequestURI();
|
||||
String fileName = uri.substring(uri.lastIndexOf("/common/stamp/") + 14);
|
||||
int paramIndex = fileName.indexOf("?");
|
||||
if (paramIndex > 0) {
|
||||
fileName = fileName.substring(0, paramIndex);
|
||||
}
|
||||
return decodeFileName(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证请求签名
|
||||
*/
|
||||
public static boolean validateRequest(HttpServletRequest request) {
|
||||
String fileName = extractFileName(request);
|
||||
String expireStr = request.getParameter("expire");
|
||||
String sign = request.getParameter("sign");
|
||||
|
||||
if (fileName == null || expireStr == null || sign == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
long expireTime = Long.parseLong(expireStr);
|
||||
return validateSign(fileName, expireTime, sign);
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static String encodeFileName(String fileName) {
|
||||
return Base64.getUrlEncoder().encodeToString(fileName.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
private static String decodeFileName(String encoded) {
|
||||
return new String(Base64.getUrlDecoder().decode(encoded), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static String md5(String input) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : digest) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("MD5 calculation failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user