- update jwt
- add security
This commit is contained in:
@@ -11,9 +11,9 @@ plugins {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api
|
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api
|
||||||
implementation("io.jsonwebtoken:jjwt-api:0.11.2")
|
implementation("io.jsonwebtoken:jjwt-api:0.12.3")
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl
|
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl
|
||||||
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.2")
|
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.3")
|
||||||
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.2")
|
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.3")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,20 @@ public class JwtSample {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String generateToken() throws InvalidKeyException {
|
public static String generateToken() throws InvalidKeyException {
|
||||||
return Jwts.builder()
|
/*return Jwts.builder()
|
||||||
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
|
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
|
||||||
.setIssuer("Elex")
|
.setIssuer("Elex")
|
||||||
.setExpiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
|
.setExpiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
|
||||||
.claim("userId", 3)
|
.claim("userId", 3)
|
||||||
.signWith(Keys.hmacShaKeyFor(key))
|
.signWith(Keys.hmacShaKeyFor(key))
|
||||||
|
.compact();*/
|
||||||
|
return Jwts.builder()
|
||||||
|
.header().type(Header.JWT_TYPE)
|
||||||
|
.and()
|
||||||
|
.issuer("Elex")
|
||||||
|
.expiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
|
||||||
|
.claim("userId", 3)
|
||||||
|
.signWith(Keys.hmacShaKeyFor(key))
|
||||||
.compact();
|
.compact();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,11 +61,16 @@ public class JwtSample {
|
|||||||
throws UnsupportedJwtException, MalformedJwtException, SignatureException, ExpiredJwtException,
|
throws UnsupportedJwtException, MalformedJwtException, SignatureException, ExpiredJwtException,
|
||||||
MissingClaimException, IncorrectClaimException {
|
MissingClaimException, IncorrectClaimException {
|
||||||
|
|
||||||
return Jwts.parserBuilder()
|
/*return Jwts.parserBuilder()
|
||||||
.setSigningKey(key)
|
.setSigningKey(key)
|
||||||
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
|
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
|
||||||
.build()
|
.build()
|
||||||
.parseClaimsJws(parseHeader(token));
|
.parseClaimsJws(parseHeader(token));*/
|
||||||
|
return Jwts.parser()
|
||||||
|
.verifyWith(Keys.hmacShaKeyFor(key))
|
||||||
|
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(parseHeader(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +97,7 @@ public class JwtSample {
|
|||||||
final String authHeader = "Bearer " + token;
|
final String authHeader = "Bearer " + token;
|
||||||
Jws<Claims> claims = parseToken(authHeader);
|
Jws<Claims> claims = parseToken(authHeader);
|
||||||
System.out.println(claims);
|
System.out.println(claims);
|
||||||
final int userId = claims.getBody().get("userId", Integer.class);
|
final int userId = claims.getPayload().get("userId", Integer.class);
|
||||||
System.out.println("User Id: " + userId);
|
System.out.println("User Id: " + userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,14 @@ package kr.pe.elex.examples;
|
|||||||
|
|
||||||
import io.jsonwebtoken.Header;
|
import io.jsonwebtoken.Header;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.io.CompressionAlgorithm;
|
||||||
import io.jsonwebtoken.security.Keys;
|
import io.jsonwebtoken.security.Keys;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.security.Key;
|
import javax.crypto.SecretKey;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
@@ -24,23 +28,39 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
class SampleTest {
|
class SampleTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test(){
|
void test() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
byte[] key = new byte[32];
|
byte[] key = new byte[32];
|
||||||
new Random().nextBytes(key);
|
new Random().nextBytes(key);
|
||||||
final Key signingKey = Keys.hmacShaKeyFor(key);
|
//final SecretKey signingKey = Keys.hmacShaKeyFor(key);
|
||||||
|
KeyPair keyPair = Jwts.SIG.RS384.keyPair().build();
|
||||||
|
PrivateKey privateKey = keyPair.getPrivate();
|
||||||
|
PublicKey publicKey = keyPair.getPublic();
|
||||||
|
String base64PublicKey = Base64.getEncoder().encodeToString(publicKey.getEncoded());
|
||||||
|
|
||||||
String jwt = Jwts.builder()
|
String jwt = Jwts.builder()
|
||||||
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
|
.header().type("JWT")
|
||||||
.setIssuer("Elex")
|
.and()
|
||||||
.setExpiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
|
.issuer("Elex")
|
||||||
|
.expiration(Date.from(Instant.now().plus(3, ChronoUnit.HOURS)))
|
||||||
.claim("userId", 3)
|
.claim("userId", 3)
|
||||||
.signWith(signingKey)
|
.signWith(keyPair.getPrivate())
|
||||||
.compact();
|
.compact();
|
||||||
System.out.println(jwt);
|
System.out.println(jwt);
|
||||||
String issuer = Jwts.parserBuilder()
|
|
||||||
.setSigningKey(signingKey)
|
X509EncodedKeySpec ukeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey));
|
||||||
//.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
|
PublicKey pKey = KeyFactory.getInstance("RSA").generatePublic(ukeySpec);
|
||||||
|
|
||||||
|
Integer userId = Jwts.parser()
|
||||||
|
.verifyWith(pKey)
|
||||||
|
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
|
||||||
.build()
|
.build()
|
||||||
.parseClaimsJws(jwt).getBody().getIssuer();
|
.parseSignedClaims(jwt).getPayload().get("userId", Integer.class);
|
||||||
System.out.println(issuer);
|
System.out.println(userId);
|
||||||
|
String alg = Jwts.parser()
|
||||||
|
.verifyWith(pKey)
|
||||||
|
.requireIssuer("Elex") // 토큰의 Issuer 일치 여부 확인
|
||||||
|
.build()
|
||||||
|
.parseSignedClaims(jwt).getHeader().getAlgorithm();
|
||||||
|
System.out.println(alg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
security/README.md
Normal file
3
security/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Security
|
||||||
|
|
||||||
|
https://github.com/jwtk/jjwt
|
||||||
14
security/build.gradle.kts
Normal file
14
security/build.gradle.kts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Examples for Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023. Elex. All Rights Reserved.
|
||||||
|
* https://www.elex-project.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("elex-java")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
}
|
||||||
20
security/logback.xml
Normal file
20
security/logback.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Examples for Java
|
||||||
|
~
|
||||||
|
~ Copyright (c) 2021. Elex. All Rights Reserved.
|
||||||
|
~ https://www.elex-project.com/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="TRACE">
|
||||||
|
<appender-ref ref="CONSOLE" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
45
security/src/main/java/kr/pe/elex/examples/AESKeys.java
Normal file
45
security/src/main/java/kr/pe/elex/examples/AESKeys.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024. Elex. All Rights Reesrved.
|
||||||
|
* https://www.elex-project.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kr.pe.elex.examples;
|
||||||
|
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class AESKeys {
|
||||||
|
public static SecretKey generateSecretKey() throws NoSuchAlgorithmException {
|
||||||
|
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||||
|
keyGenerator.init(128, new SecureRandom());
|
||||||
|
return keyGenerator.generateKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SecretKey generateSecretKey(char[] password, byte[] salt, int iteration) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
PBEKeySpec keySpec = new PBEKeySpec(password, salt, iteration);
|
||||||
|
return SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_128")
|
||||||
|
.generateSecret(keySpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeSecretKey(final SecretKey secretKey){
|
||||||
|
return Base64.getEncoder().encodeToString(secretKey.getEncoded());
|
||||||
|
}
|
||||||
|
public static SecretKey decodeSecretKey(final String secretKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
SecretKey keySpec = new SecretKeySpec(Base64.getDecoder().decode(secretKey), "AES");
|
||||||
|
return keySpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IvParameterSpec generateIV(byte[] iv){
|
||||||
|
IvParameterSpec parameterSpec = new IvParameterSpec(iv);
|
||||||
|
return parameterSpec;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
security/src/main/java/kr/pe/elex/examples/RSAKeys.java
Normal file
44
security/src/main/java/kr/pe/elex/examples/RSAKeys.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Examples for Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||||
|
* https://www.elex-project.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kr.pe.elex.examples;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class RSAKeys {
|
||||||
|
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
|
||||||
|
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
|
||||||
|
keyPairGen.initialize(2048, new SecureRandom());
|
||||||
|
return keyPairGen.generateKeyPair();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodePrivateKey(final PrivateKey privateKey) {
|
||||||
|
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodePublicKey(final PublicKey publicKey) {
|
||||||
|
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PublicKey decodePublicKey(final String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
|
||||||
|
return KeyFactory.getInstance("RSA").generatePublic(keySpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrivateKey decodePrivateKey(final String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(privateKey));
|
||||||
|
return KeyFactory.getInstance("RSA").generatePrivate(keySpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Examples for Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||||
|
* https://www.elex-project.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kr.pe.elex.examples;
|
||||||
40
security/src/test/java/kr/pe/elex/examples/AESKeysTest.java
Normal file
40
security/src/test/java/kr/pe/elex/examples/AESKeysTest.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024. Elex. All Rights Reesrved.
|
||||||
|
* https://www.elex-project.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kr.pe.elex.examples;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class AESKeysTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
SecretKey secretKey = AESKeys.generateSecretKey();
|
||||||
|
|
||||||
|
String base64SecretKey = AESKeys.encodeSecretKey(secretKey);
|
||||||
|
|
||||||
|
SecretKey secretKey1 = AESKeys.decodeSecretKey(base64SecretKey);
|
||||||
|
|
||||||
|
assertEquals(secretKey, secretKey1);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
void test1() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
byte[] salt = new byte[8];
|
||||||
|
new Random().nextBytes(salt);
|
||||||
|
SecretKey secretKey = AESKeys.generateSecretKey("Hello".toCharArray(), salt, 10);
|
||||||
|
|
||||||
|
SecretKey secretKey1 = AESKeys.generateSecretKey("Hello".toCharArray(), salt, 10);
|
||||||
|
|
||||||
|
assertEquals(secretKey, secretKey1);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
security/src/test/java/kr/pe/elex/examples/SampleTest.java
Normal file
21
security/src/test/java/kr/pe/elex/examples/SampleTest.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Examples for Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||||
|
* https://www.elex-project.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kr.pe.elex.examples;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
|
||||||
|
class SampleTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test() throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,5 +15,5 @@ include(
|
|||||||
"xml", "jackson", "jsoup", "markdown", "network", "httpd",
|
"xml", "jackson", "jsoup", "markdown", "network", "httpd",
|
||||||
"properties", "serial-io",
|
"properties", "serial-io",
|
||||||
"mustache", "thymeleaf", "locale", "quartz", "sysinfo",
|
"mustache", "thymeleaf", "locale", "quartz", "sysinfo",
|
||||||
"imaging", "stream", "sound", "midi", "gson"
|
"imaging", "stream", "sound", "midi", "gson", "security"
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user