Initial commit: PAR Server with Spring Boot 3.2, MyBatis-Plus, Flyway
This commit is contained in:
37
par-common/pom.xml
Normal file
37
par-common/pom.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.par</groupId>
|
||||
<artifactId>par-server</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>par-common</artifactId>
|
||||
<name>PAR Common</name>
|
||||
<description>Common utilities, constants, and shared models</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
81
par-common/src/main/java/com/par/common/util/HmacUtil.java
Normal file
81
par-common/src/main/java/com/par/common/util/HmacUtil.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package com.par.common.util;
|
||||
|
||||
import org.apache.commons.codec.digest.HmacUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* HMAC 签名工具类
|
||||
*/
|
||||
public class HmacUtil {
|
||||
|
||||
private static final String HMAC_ALGORITHM = "HmacSHA256";
|
||||
|
||||
/**
|
||||
* 生成 HMAC-SHA256 签名
|
||||
*
|
||||
* @param secret 密钥
|
||||
* @param data 待签名数据
|
||||
* @return Base64 编码的签名
|
||||
*/
|
||||
public static String sign(String secret, String data) {
|
||||
byte[] signature = new HmacUtils(HMAC_ALGORITHM, secret).hmac(data);
|
||||
return Base64.getEncoder().encodeToString(signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证签名
|
||||
*
|
||||
* @param secret 密钥
|
||||
* @param data 待签名数据
|
||||
* @param signature 待验证的签名
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean verify(String secret, String data, String signature) {
|
||||
String expected = sign(secret, data);
|
||||
return MessageDigest.isEqual(
|
||||
signature.getBytes(StandardCharsets.UTF_8),
|
||||
expected.getBytes(StandardCharsets.UTF_8)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建签名内容字符串
|
||||
* 格式: METHOD\nPATH\nTIMESTAMP\nBODY_SHA256
|
||||
*/
|
||||
public static String buildSignContent(String method, String path, long timestamp, String bodySha256) {
|
||||
return method.toUpperCase() + "\n" + path + "\n" + timestamp + "\n" + bodySha256;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算 SHA-256 哈希
|
||||
*/
|
||||
public static String sha256(String input) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
|
||||
return bytesToHex(hash);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("SHA-256 algorithm not available", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成匿名ID(邮箱SHA-256前16位)
|
||||
*/
|
||||
public static String generateAnonymousId(String email) {
|
||||
String hash = sha256(email.toLowerCase().trim());
|
||||
return hash.substring(0, 16);
|
||||
}
|
||||
|
||||
private static String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.par.common.util;
|
||||
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
/**
|
||||
* 密码工具类
|
||||
*/
|
||||
public class PasswordUtil {
|
||||
|
||||
private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
|
||||
/**
|
||||
* 加密密码
|
||||
*/
|
||||
public static String encode(String rawPassword) {
|
||||
return encoder.encode(rawPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证密码
|
||||
*/
|
||||
public static boolean matches(String rawPassword, String encodedPassword) {
|
||||
return encoder.matches(rawPassword, encodedPassword);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user