이 클래스는 두 개의 공공 방법, 그것의 유효성을 확인하는 토큰과 다른를 생성하기위한 하나입니다. 훨씬 더 크고 복잡한 코드에서 요약되므로 일부 오류가 발생할 수 있습니다. 일부 테스트가 포함되어있어 즉시 테스트 할 수 있습니다. 어떤 방법 으로든, 나는 당신을 올바른 길로 인도하기에 충분할 것이라고 희망합니다.
package tokens;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class TokenUtils {
private static final String HMAC_ALGO = "HmacSHA256";
private static final String TOKEN_SEPARATOR = ":";
private static final long MAX_AGE = 1_000 * 60 * 60 * 24; // 24h
private TokenUtils() {
}
public static String createToken(String username, long timestamp, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
StringBuilder sb = new StringBuilder();
sb.append(generateTokenStringPublicPart(username, timestamp));
sb.append(TOKEN_SEPARATOR);
sb.append(computeSignature(username, timestamp, secretKey));
return sb.toString();
}
public static boolean verifyToken(String token, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
String[] parts = token.split(TOKEN_SEPARATOR);
boolean result = false;
if (parts.length == 3) {
String username = parts[0];
Long timestamp = Long.valueOf(parts[1]);
String signature = parts[2];
if (signature.equals(computeSignature(username, timestamp, secretKey))) {
if (System.currentTimeMillis() - timestamp < MAX_AGE) {
result = true;
}
}
}
return result;
}
private static String generateTokenStringPublicPart(String username, long timestamp) {
StringBuilder sb = new StringBuilder();
sb.append(username);
sb.append(TOKEN_SEPARATOR);
sb.append(timestamp);
return sb.toString();
}
private static String computeSignature(String username, long timestamp, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
StringBuilder sb = new StringBuilder();
sb.append(generateTokenStringPublicPart(username, timestamp));
SecretKeySpec sks = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), HMAC_ALGO);
Mac hmac = Mac.getInstance(HMAC_ALGO);
hmac.init(sks);
return Base64.getUrlEncoder().encodeToString(hmac.doFinal(sb.toString().getBytes(StandardCharsets.UTF_8)));
}
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
String secretKey = "secret_key";
String token = TokenUtils.createToken("marko", System.currentTimeMillis(), secretKey);
System.out.println(token);
System.out.println("Original token verification: " + TokenUtils.verifyToken(token, secretKey));
token = token.replaceAll("a", "b");
System.out.println("Tampered token verification: " + TokenUtils.verifyToken(token, secretKey));
token = TokenUtils.createToken("marko", System.currentTimeMillis() - 1_000 * 60 * 60 * 48, secretKey);
System.out.println("Expired token verification: " + TokenUtils.verifyToken(token, secretKey));
}
}
암호화를 사용할 때 어떤 유형의 공격을 방지해야할까요? 참고 : 보내는 모든 링크의 키를 변경하지 않으면 XOR은 매우 나쁜 생각입니다. –
JodaTime이 암호화하는 동안 문제가 너무 많아서 시간 차이가 24 시간 미만인지 확인하고 싶다면 Calender를 사용할 수도 있습니다. –
암호화를 사용하면 암호화가 모든 것을 상태 비 저장으로 만들지 만 원하니? 그렇지 않은 경우 데이터베이스에 현재 또는 최대 허용 시간을 저장하고 리셋 요청이 들어 왔을 때 비교하는 것이 어떻습니까? –