重构了 jwt , 支持黑名单机制
diff --git a/config/application-devel-pg-local.properties b/config/application-devel-pg-local.properties
index 175bb6b..ad1ccb2 100644
--- a/config/application-devel-pg-local.properties
+++ b/config/application-devel-pg-local.properties
@@ -7,6 +7,7 @@
spring.datasource.url=jdbc:postgresql://localhost:5432/payapi
spring.datasource.username=payapi
spring.datasource.password=123456
+database.dbtype=postgresql
# Redis settings
redis.server=localhost
redis.port=6379
diff --git a/config/application-devel-pg.properties b/config/application-devel-pg.properties
index 92b7ecf..d21bd66 100644
--- a/config/application-devel-pg.properties
+++ b/config/application-devel-pg.properties
@@ -3,6 +3,7 @@
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
+database.dbtype=postgresql
# Postgresql settings
spring.datasource.url=jdbc:postgresql://172.28.201.70:15432/payapi
spring.datasource.username=payapi
diff --git a/src/main/java/com/supwisdom/dlpay/framework/core/DatabaseConfig.java b/src/main/java/com/supwisdom/dlpay/framework/core/DatabaseConfig.java
new file mode 100644
index 0000000..16f454a
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/core/DatabaseConfig.java
@@ -0,0 +1,18 @@
+package com.supwisdom.dlpay.framework.core;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class DatabaseConfig {
+ @Value("${database.dbtype:oracle}")
+ private String dbType;
+
+ public String getDbType() {
+ return dbType;
+ }
+
+ public void setDbType(String dbType) {
+ this.dbType = dbType;
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/core/JwtToken.java b/src/main/java/com/supwisdom/dlpay/framework/core/JwtToken.java
new file mode 100644
index 0000000..072ea5d
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/core/JwtToken.java
@@ -0,0 +1,39 @@
+package com.supwisdom.dlpay.framework.core;
+
+import org.jose4j.jwt.NumericDate;
+
+public class JwtToken {
+ private String jti;
+ private NumericDate expiration;
+ private String jwtToken;
+
+ public JwtToken(String jti, String jwtToken, NumericDate exp) {
+ this.jti = jti;
+ this.jwtToken = jwtToken;
+ this.expiration = exp;
+ }
+
+ public String getJti() {
+ return jti;
+ }
+
+ public void setJti(String jti) {
+ this.jti = jti;
+ }
+
+ public String getJwtToken() {
+ return jwtToken;
+ }
+
+ public void setJwtToken(String jwtToken) {
+ this.jwtToken = jwtToken;
+ }
+
+ public NumericDate getExpiration() {
+ return expiration;
+ }
+
+ public void setExpiration(NumericDate expiration) {
+ this.expiration = expiration;
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java b/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java
index 20344ab..9c0a35b 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/core/JwtTokenUtil.java
@@ -5,6 +5,7 @@
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
+import org.jose4j.jwt.MalformedClaimException;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
@@ -26,7 +27,7 @@
return jwtConfig.getHeader();
}
- public String generateToken(Map<String, Object> params) throws JoseException {
+ public JwtToken generateToken(Map<String, Object> params) throws JoseException, MalformedClaimException {
JwtClaims claims = new JwtClaims();
claims.setIssuer(params.get("issuer").toString()); // who creates the token and signs it
if (params.get("audience") != null) {
@@ -57,16 +58,16 @@
jws.setKey(key.getKey());
jws.setKeyIdHeaderValue(key.getKeyId());
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
- return jws.getCompactSerialization();
+ return new JwtToken(claims.getJwtId(), jws.getCompactSerialization(), claims.getExpirationTime());
}
- public String generateToken(UserDetails userDetails) throws JoseException {
+ public JwtToken generateToken(UserDetails userDetails) throws JoseException, MalformedClaimException {
Map<String, Object> claims = new HashMap<>();
claims.put("uid", userDetails.getUsername());
return generateToken(claims);
}
- public Map<String, List<Object>> verifyToken(String token) throws JoseException, InvalidJwtException {
+ public Map<String, Object> verifyToken(String token) throws JoseException, InvalidJwtException {
Map<String, Object> keySpec = new HashMap<>();
keySpec.put("kty", "oct");
keySpec.put("k", jwtConfig.getSecret());
@@ -74,9 +75,8 @@
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setRequireExpirationTime() // the JWT must have an expiration time
.setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew
- .setRequireSubject() // the JWT must have a subject claim
- .setExpectedIssuer("supwisdom") // whom the JWT needs to have been issued by
.setVerificationKey(key.getKey()) // verify the signature with the public key
+ .setSkipDefaultAudienceValidation()
.setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context
new AlgorithmConstraints(org.jose4j.jwa.AlgorithmConstraints.ConstraintType.WHITELIST, // which is only RS256 here
AlgorithmIdentifiers.HMAC_SHA256))
@@ -84,24 +84,6 @@
// Validate the JWT and process it to the Claims
JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
- System.out.println("JWT validation succeeded! " + jwtClaims);
- return jwtClaims.flattenClaims();
- // InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway.
- // Hopefully with meaningful explanations(s) about what went wrong.
-
-// // Programmatic access to (some) specific reasons for JWT invalidity is also possible
-// // should you want different error handling behavior for certain conditions.
-//
-// // Whether or not the JWT has expired being one common reason for invalidity
-// if (e.hasExpired())
-// {
-// System.out.println("JWT expired at " + e.getJwtContext().getJwtClaims().getExpirationTime());
-// }
-//
-// // Or maybe the audience was invalid
-// if (e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID))
-// {
-// System.out.println("JWT had wrong audience: " + e.getJwtContext().getJwtClaims().getAudience());
-// }
+ return jwtClaims.getClaimsMap();
}
}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/dao/TaskLockDao.java b/src/main/java/com/supwisdom/dlpay/framework/dao/TaskLockDao.java
index 6c36c5d..576c089 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/dao/TaskLockDao.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/dao/TaskLockDao.java
@@ -21,12 +21,14 @@
@Query(value = "select to_char(sysdate,'yyyymmdd') as hostdate,to_char(sysdate,'hh24miss') as hosttime,to_char(sysdate,'yyyymmddhh24miss') as hostdatetime, sysdate from dual", nativeQuery = true)
SystemDateTime getOracleDatetime();
+ @Query(value = "select to_char(CURRENT_TIMESTAMP,'yyyymmdd') as hostdate," + "" +
+ "to_char(CURRENT_TIMESTAMP,'hh24miss') as hosttime,to_char(CURRENT_TIMESTAMP,'yyyymmddhh24miss') as hostdatetime," +
+ " CURRENT_TIMESTAMP as sysdate", nativeQuery = true)
+ SystemDateTime getPGDatetime();
+
@Query(value = " select to_char(sysdate,'yyyyMMddhh24miss')||to_char(SEQ_REFNO.nextval,'FM000000') as billno from dual ", nativeQuery = true)
String getOracleRefno();
-
-
-
//================= database=PG =================//
@Query(value = " select to_char(CURRENT_TIMESTAMP,'yyyyMMddhh24miss')||to_char(nextval('SEQ_REFNO'),'FM000000') as billno ", nativeQuery = true)
String getPgRefno();
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/ApiClientRedis.java b/src/main/java/com/supwisdom/dlpay/framework/domain/ApiClientRedis.java
index 2cb43eb..d7bb016 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/domain/ApiClientRedis.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/ApiClientRedis.java
@@ -1,8 +1,8 @@
package com.supwisdom.dlpay.framework.domain;
+import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
-import javax.persistence.Id;
@RedisHash("app_client")
public class ApiClientRedis {
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/DateItem.java b/src/main/java/com/supwisdom/dlpay/framework/domain/DateItem.java
deleted file mode 100644
index f4aa56e..0000000
--- a/src/main/java/com/supwisdom/dlpay/framework/domain/DateItem.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.supwisdom.dlpay.framework.domain;
-
-import javax.persistence.*;
-import java.sql.Date;
-
-@Entity
-public class DateItem {
- private Date date;
-
- /**
- * @return the date
- */
- @Id
- @Column(name = "DATE_VALUE")
- public Date getDate() {
- return date;
- }
-
- /**
- * @param date
- * the date to set
- */
- public void setDate(Date date) {
- this.date = date;
- }
-}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java b/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java
new file mode 100644
index 0000000..6064748
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java
@@ -0,0 +1,39 @@
+package com.supwisdom.dlpay.framework.domain;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.redis.core.RedisHash;
+
+
+@RedisHash("api_jwt")
+public class JwtRedis {
+ @Id
+ String jti;
+
+ String status;
+
+ Long expiration;
+
+ public String getJti() {
+ return jti;
+ }
+
+ public void setJti(String jti) {
+ this.jti = jti;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public Long getExpiration() {
+ return expiration;
+ }
+
+ public void setExpiration(Long expiration) {
+ this.expiration = expiration;
+ }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/PersonRedis.java b/src/main/java/com/supwisdom/dlpay/framework/domain/PersonRedis.java
index 2c25864..623e55a 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/domain/PersonRedis.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/PersonRedis.java
@@ -1,9 +1,8 @@
package com.supwisdom.dlpay.framework.domain;
+import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
-import javax.persistence.Id;
-
@RedisHash("person")
public class PersonRedis {
@Id
diff --git a/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java
new file mode 100644
index 0000000..38a3fbe
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/framework/redisrepo/ApiJwtRepository.java
@@ -0,0 +1,7 @@
+package com.supwisdom.dlpay.framework.redisrepo;
+
+import com.supwisdom.dlpay.framework.domain.JwtRedis;
+import org.springframework.data.repository.CrudRepository;
+
+public interface ApiJwtRepository extends CrudRepository<JwtRedis, String> {
+}
diff --git a/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java b/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java
index 0cf7bcf..07d5e63 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/service/impl/SystemUtilServiceImpl.java
@@ -1,10 +1,10 @@
package com.supwisdom.dlpay.framework.service.impl;
+import com.supwisdom.dlpay.framework.core.DatabaseConfig;
import com.supwisdom.dlpay.framework.dao.SettleCtlDao;
import com.supwisdom.dlpay.framework.dao.TaskLockDao;
import com.supwisdom.dlpay.framework.dao.TranscodeDao;
import com.supwisdom.dlpay.framework.data.SystemDateTime;
-import com.supwisdom.dlpay.framework.domain.DateItem;
import com.supwisdom.dlpay.framework.domain.TSettlectl;
import com.supwisdom.dlpay.framework.domain.TTaskLock;
import com.supwisdom.dlpay.framework.domain.TTranscode;
@@ -15,18 +15,13 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
public class SystemUtilServiceImpl implements SystemUtilService {
- @PersistenceContext
- EntityManager em;
+ @Autowired
+ private DatabaseConfig databaseConfig;
@Autowired
private TaskLockDao taskLockDao;
@@ -70,17 +65,21 @@
* 获取oracle数据库时间
*/
private SystemDateTime getOracleDatetime() {
-// return taskLockDao.getOracleDatetime();
- String sql = "SELECT CURRENT_TIMESTAMP AS DATE_VALUE";
- Query query = em.createNativeQuery(sql, DateItem.class);
- DateItem dateItem = (DateItem) query.getSingleResult();
- SystemDateTime now = new SystemDateTimeImpl(dateItem.getDate());
- return now;
+ return taskLockDao.getOracleDatetime();
+ }
+
+ private SystemDateTime getPGDatetime() {
+ return taskLockDao.getPGDatetime();
}
@Override
public SystemDateTime getSysdatetime() {
- return getOracleDatetime();
+ switch (databaseConfig.getDbType()) {
+ case "postgresql":
+ return getPGDatetime();
+ default:
+ return getOracleDatetime();
+ }
}
@Override
diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java b/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
index 5596b24..6b45836 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java
@@ -12,6 +12,12 @@
public static final String STATUS_LOCKED = "locked";
/**
+ * JWT 状态
+ */
+ public static final String JWT_STATUS_NORMAL = "normal";
+ public static final String JWT_STATUS_BLACKLIST = "blacklist";
+
+ /**
* 流水状态
* temp -- 临时流水
* init -- 初始化流水
@@ -35,20 +41,20 @@
/**
* 支付方式
- * */
- public static final String PAYTYPE_CASH="cash";
- public static final String PAYTYPE_BALANCE="balance";
+ */
+ public static final String PAYTYPE_CASH = "cash";
+ public static final String PAYTYPE_BALANCE = "balance";
/**
* feetype
* - 消费:折扣、搭伙费(管理费)
* - 充值:优惠、服务费(手续费)
- * */
+ */
- public static final String FEETYPE_CONSUME_MEALER="mealer"; //收管理费
- public static final String FEETYPE_CONSUME_DISCOUNT="discount"; //折扣款抵扣
+ public static final String FEETYPE_CONSUME_MEALER = "mealer"; //收管理费
+ public static final String FEETYPE_CONSUME_DISCOUNT = "discount"; //折扣款抵扣
- public static final String PAYTYPE_RECHARGE_COUPON="coupon"; // 充值优惠
- public static final String PAYTYPE_RECHARGE_SERVICEFEE="servicefee"; //收服务费
+ public static final String PAYTYPE_RECHARGE_COUPON = "coupon"; // 充值优惠
+ public static final String PAYTYPE_RECHARGE_SERVICEFEE = "servicefee"; //收服务费
}
diff --git a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
index 5bcea3a..521fe7c 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
@@ -7,12 +7,13 @@
import com.supwisdom.dlpay.framework.security.validate.ImageCodeUtil
import com.supwisdom.dlpay.framework.security.validate.VerifyCode
import com.supwisdom.dlpay.framework.domain.ApiClientRedis
+import com.supwisdom.dlpay.framework.domain.JwtRedis
import com.supwisdom.dlpay.framework.domain.TOperator
import com.supwisdom.dlpay.framework.redisrepo.ApiClientRepository
-import com.supwisdom.dlpay.framework.security.OperUtil
-import com.supwisdom.dlpay.framework.service.OperatorDetailService
+import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.HmacUtil
+import com.supwisdom.dlpay.framework.util.TradeDict
import com.supwisdom.dlpay.system.service.CommonService
import com.supwisdom.dlpay.system.service.FunctionService
import mu.KotlinLogging
@@ -38,10 +39,13 @@
class ApiAuthController {
@Autowired
- lateinit var repo: ApiClientRepository
+ lateinit var apiClientRepository: ApiClientRepository
@Autowired
- lateinit var apiClient: ApiClientDao
+ lateinit var apiJwtRepository: ApiJwtRepository
+
+ @Autowired
+ lateinit var apiClientDao: ApiClientDao
@Autowired
lateinit var systemUtil: SystemUtilService
@@ -49,9 +53,9 @@
@Autowired
lateinit var jwtConfig: JwtConfig
- @GetMapping("/gettoken")
- fun loginInit(appid: String): ResponseEntity<Any> {
- apiClient.findById(appid).run {
+ @GetMapping(value = ["/gettoken", "/gettoken/{clientid}"])
+ fun loginInit(appid: String, @PathVariable clientid: String?): ResponseEntity<Any> {
+ apiClientDao.findById(appid).run {
if (!isPresent) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
@@ -64,12 +68,12 @@
val token = generateRandomToken()
val now = systemUtil.sysdatetime.hostdatetime
ApiClientRedis().apply {
- id = appid
+ id = if (clientid == null) appid else "$appid-$clientid"
loginTimestamp = now
roles = it.roles
this.token = HmacUtil.HMACSHA256(token, it.secret)
}.also {
- repo.save(it)
+ apiClientRepository.save(it)
}
return ResponseEntity.ok(ResponseBodyBuilder.create()
.data("token", token)
@@ -88,20 +92,25 @@
return (api.token == secret)
}
- @GetMapping("/authentication")
- fun login(appid: String, secret: String): ResponseEntity<Any> {
- return repo.findById(appid).let {
+ @GetMapping(value = ["/authentication", "/authentication/{clientid}"])
+ fun login(appid: String, secret: String, @PathVariable clientid: String?): ResponseEntity<Any> {
+ val requestId = if (clientid == null) appid else "$appid-$clientid"
+ return apiClientRepository.findById(requestId).let {
if (it.isPresent && checkSecretToken(it.get(), secret)) {
- it.get().also { client ->
- client.token = ""
- repo.save(client)
- }
+ apiClientRepository.delete(it.get())
val token = JwtTokenUtil(jwtConfig).generateToken(
- mapOf("uid" to appid, "issuer" to "supwisdom",
- "subject" to "payapi",
+ mapOf("uid" to appid, "issuer" to "payapi",
+ "audience" to (clientid ?: appid),
"authorities" to it.get().roles.split(";")))
+ JwtRedis().apply {
+ jti = token.jti
+ status = TradeDict.JWT_STATUS_NORMAL
+ expiration = token.expiration.value
+ }.apply {
+ apiJwtRepository.save(this)
+ }
ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("jwt", token)
+ .data("jwt", token.jwtToken)
.data("appid", appid)
.success())
} else {
diff --git a/src/main/kotlin/com/supwisdom/dlpay/security.kt b/src/main/kotlin/com/supwisdom/dlpay/security.kt
index 491cc46..abb1dd7 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -3,9 +3,12 @@
import com.supwisdom.dlpay.framework.core.JwtConfig
import com.supwisdom.dlpay.framework.core.JwtTokenUtil
import com.supwisdom.dlpay.framework.core.PasswordBCryptConfig
+import com.supwisdom.dlpay.framework.redisrepo.ApiJwtRepository
import com.supwisdom.dlpay.framework.security.ValidateCodeSecurityConfig
import com.supwisdom.dlpay.framework.service.OperatorDetailService
+import com.supwisdom.dlpay.framework.util.TradeDict
import org.jose4j.jwt.consumer.InvalidJwtException
+import org.jose4j.lang.JoseException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@@ -26,6 +29,7 @@
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
+import org.springframework.stereotype.Component
import org.springframework.web.filter.OncePerRequestFilter
import java.security.SecureRandom
import javax.servlet.FilterChain
@@ -34,18 +38,50 @@
import javax.sql.DataSource
-class ApiJwtAuthenticationFilter(jwt: JwtTokenUtil) : OncePerRequestFilter() {
- private val jwtUtil = jwt
+@Component
+class ApiJwtAuthenticationFilter : OncePerRequestFilter() {
+ @Autowired
+ lateinit var jwtConfig: JwtConfig
+
+ @Autowired
+ lateinit var apiJwtRepository: ApiJwtRepository
+
+ private var jwtUtil: JwtTokenUtil? = null
+
+
+ private fun getUtil(): JwtTokenUtil {
+ if (jwtUtil == null) {
+ jwtUtil = JwtTokenUtil((jwtConfig))
+ }
+ return jwtUtil as JwtTokenUtil
+ }
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
- request.getHeader(jwtUtil.header)?.let { jwt ->
+ request.getHeader(jwtConfig.header)?.let { jwt ->
try {
- val claims = jwtUtil.verifyToken(jwt)
+ val claims = getUtil().verifyToken(jwt)
+ apiJwtRepository.findById(claims["jti"].toString()).let {
+ if (!it.isPresent) {
+ throw JoseException("JWT has not been register")
+ }
+ if (it.get().status != TradeDict.JWT_STATUS_NORMAL) {
+ throw JoseException("JWT status error : ${it.get().status}")
+ }
+ }
val auth = UsernamePasswordAuthenticationToken(claims["uid"], null,
- claims["authorities"]?.map { SimpleGrantedAuthority(it as String) })
+ (claims["authorities"] as ArrayList<*>)
+ .map { SimpleGrantedAuthority(it as String) })
SecurityContextHolder.getContext().authentication = auth
} catch (e: InvalidJwtException) {
- SecurityContextHolder.clearContext();
+ SecurityContextHolder.clearContext()
+ if (e.hasExpired()) {
+ apiJwtRepository.deleteById(e.jwtContext.jwtClaims.jwtId)
+ response.sendError(HttpStatus.UNAUTHORIZED.value(), e.message)
+ } else {
+ response.sendError(HttpStatus.BAD_REQUEST.value(), e.message)
+ }
+ } catch (e: JoseException) {
+ SecurityContextHolder.clearContext()
response.sendError(HttpStatus.BAD_REQUEST.value(), e.message)
}
}
@@ -62,13 +98,13 @@
class ApiWebSecurityConfigurationAdapter : WebSecurityConfigurerAdapter() {
@Autowired
- lateinit var jwtConfig: JwtConfig
+ lateinit var apiFilter: ApiJwtAuthenticationFilter
override fun configure(http: HttpSecurity) {
// 设置 API 访问权限管理
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
- .addFilterAfter(ApiJwtAuthenticationFilter(JwtTokenUtil(jwtConfig)),
+ .addFilterAfter(apiFilter,
UsernamePasswordAuthenticationFilter::class.java)
.antMatcher("/api/**")
.authorizeRequests()