Redis jti repository impl/ test
parent
a5592cf054
commit
688c47a6f6
4
pom.xml
4
pom.xml
|
@ -65,6 +65,10 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -39,7 +39,8 @@ public class ClaimsOAuth2TokenCustomizer implements OAuth2TokenCustomizer<JwtEnc
|
|||
|
||||
JwtClaimsSet.Builder claims = context.getClaims();
|
||||
//jti
|
||||
claims.id(GuidGenerator.generateNumber());
|
||||
String jti = GuidGenerator.generateNumber();
|
||||
claims.id(jti);
|
||||
|
||||
//根据不同的 scope 与 tokenType添加扩展属性
|
||||
OAuth2TokenType tokenType = context.getTokenType();
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package com.monkeyk.sos.domain.oauth;
|
||||
|
||||
/**
|
||||
* 2025/5/28 17:19
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @since 3.0.1
|
||||
*/
|
||||
public interface JtiRepository {
|
||||
|
||||
|
||||
/**
|
||||
* 保存 JtiToken
|
||||
*
|
||||
* @param jtiToken JtiToken
|
||||
* @param ttl 有效时间,秒
|
||||
*/
|
||||
void saveJtiToken(JtiToken jtiToken, long ttl);
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*
|
||||
* @param jti jti
|
||||
* @return JtiToken
|
||||
*/
|
||||
JtiToken findByJti(String jti);
|
||||
|
||||
/**
|
||||
* 判断对应的 jti 是否存在(一般存在表示还可用?),根据 jti
|
||||
*
|
||||
* @param jti jti
|
||||
* @return true 存在
|
||||
*/
|
||||
boolean existJti(String jti);
|
||||
|
||||
/**
|
||||
* 删除 Jti 数据
|
||||
*
|
||||
* @param jti jti
|
||||
* @return 删除成功返回 true
|
||||
*/
|
||||
Boolean removeJtiToken(String jti);
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.monkeyk.sos.domain.oauth;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 2025/5/28 17:16
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public class JtiToken implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -6826558386135443094L;
|
||||
|
||||
|
||||
/**
|
||||
* jti值,从id_token 获取
|
||||
*/
|
||||
private String jti;
|
||||
|
||||
/**
|
||||
* OAuth2 clientId
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* user id,可选
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
// 可扩展其他属性
|
||||
|
||||
|
||||
public JtiToken() {
|
||||
}
|
||||
|
||||
public String getJti() {
|
||||
return jti;
|
||||
}
|
||||
|
||||
public JtiToken setJti(String jti) {
|
||||
this.jti = jti;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public JtiToken setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public JtiToken setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" +
|
||||
"jti='" + jti + '\'' +
|
||||
", clientId='" + clientId + '\'' +
|
||||
", userId='" + userId + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package com.monkeyk.sos.infrastructure.redis;
|
||||
|
||||
import com.monkeyk.sos.domain.oauth.JtiRepository;
|
||||
import com.monkeyk.sos.domain.oauth.JtiToken;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.BoundValueOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 2025/5/28 17:22
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @since 3.0.1
|
||||
*/
|
||||
|
||||
@Repository
|
||||
public class JtiRepositoryRedis implements JtiRepository {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JtiRepositoryRedis.class);
|
||||
|
||||
/**
|
||||
* KEY的格式
|
||||
*/
|
||||
private static final String KEY_FORMAT = "sos-jti-%s";
|
||||
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* 统一加前缀
|
||||
*
|
||||
* @param jti jti
|
||||
* @return redis key
|
||||
*/
|
||||
private String getJtiRedisKey(String jti) {
|
||||
return String.format(KEY_FORMAT, jti);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void saveJtiToken(JtiToken jtiToken, long ttl) {
|
||||
if (ttl <= 0) {
|
||||
throw new IllegalArgumentException("ttl must be greater than 0");
|
||||
}
|
||||
String redisKey = getJtiRedisKey(jtiToken.getJti());
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("saveJtiToken, jtiToken: {}, ttl: {}", jtiToken, ttl);
|
||||
}
|
||||
BoundValueOperations<Object, Object> bvo = this.redisTemplate.boundValueOps(redisKey);
|
||||
bvo.set(jtiToken, ttl, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public JtiToken findByJti(String jti) {
|
||||
String redisKey = getJtiRedisKey(jti);
|
||||
BoundValueOperations<Object, Object> bvo = this.redisTemplate.boundValueOps(redisKey);
|
||||
return (JtiToken) bvo.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean existJti(String jti) {
|
||||
String redisKey = getJtiRedisKey(jti);
|
||||
Boolean has = this.redisTemplate.hasKey(redisKey);
|
||||
return has != null ? has : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Boolean removeJtiToken(String jti) {
|
||||
String redisKey = getJtiRedisKey(jti);
|
||||
return this.redisTemplate.delete(redisKey);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -24,11 +24,12 @@ spring.security.oauth2.authorizationserver.issuer=http://127.0.0.1:${server.port
|
|||
#
|
||||
# Redis
|
||||
#
|
||||
spring.data.redis.host=localhost
|
||||
spring.data.redis.host=127.0.0.1
|
||||
spring.data.redis.port=6379
|
||||
spring.data.redis.database=5
|
||||
spring.data.redis.password=
|
||||
spring.data.redis.timeout=2000
|
||||
spring.data.redis.lettuce.pool.enabled=true
|
||||
#
|
||||
# Condition Config
|
||||
# @since 2.1.0
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.monkeyk.sos.infrastructure.redis;
|
||||
|
||||
import com.monkeyk.sos.domain.oauth.JtiToken;
|
||||
import com.monkeyk.sos.infrastructure.AbstractRepositoryTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* 2025/5/28 17:33
|
||||
*
|
||||
* @author Shengzhao Li
|
||||
* @since 3.0.1
|
||||
*/
|
||||
//@Transactional
|
||||
class JtiRepositoryRedisTest extends AbstractRepositoryTest {
|
||||
|
||||
|
||||
@Autowired
|
||||
private JtiRepositoryRedis repositoryRedis;
|
||||
|
||||
@Test
|
||||
void saveJtiToken() {
|
||||
|
||||
JtiToken jtiToken = new JtiToken()
|
||||
.setJti("jti").setClientId("clientId").setUserId("userId");
|
||||
|
||||
repositoryRedis.saveJtiToken(jtiToken, 1000);
|
||||
|
||||
repositoryRedis.removeJtiToken(jtiToken.getJti());
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByJti() {
|
||||
|
||||
JtiToken jtiToken = repositoryRedis.findByJti("jti");
|
||||
assertNull(jtiToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
void existJti() {
|
||||
|
||||
boolean exist = repositoryRedis.existJti("jti");
|
||||
assertFalse(exist);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue