优化 jwt ,增加了 jwt refresh 接口
diff --git a/src/main/java/com/supwisdom/dlpay/framework/core/JwtConfig.java b/src/main/java/com/supwisdom/dlpay/framework/core/JwtConfig.java
index 1eccb8a..a51f705 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/core/JwtConfig.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/core/JwtConfig.java
@@ -11,6 +11,8 @@
   private Long expiration = 3600L;
   @Value("${jwt.header:Authorization}")
   private String header = "Authorization";
+  @Value("${jwt.token_header:Bearer")
+  private String tokenHeader = "Bearer";
 
   public String getSecret() {
     return secret;
@@ -23,4 +25,8 @@
   public String getHeader() {
     return header;
   }
+
+  public String getTokenHeader() {
+    return tokenHeader;
+  }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java b/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java
index 6064748..01828e0 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/domain/JwtRedis.java
@@ -11,6 +11,8 @@
 
   String status;
 
+  String uid;
+
   Long expiration;
 
   public String getJti() {
@@ -36,4 +38,12 @@
   public void setExpiration(Long expiration) {
     this.expiration = expiration;
   }
+
+  public String getUid() {
+    return uid;
+  }
+
+  public void setUid(String uid) {
+    this.uid = uid;
+  }
 }
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 521fe7c..ec1d2e4 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
@@ -29,6 +29,7 @@
 import org.springframework.ui.Model
 import org.springframework.web.bind.annotation.*
 import org.springframework.web.context.request.ServletWebRequest
+import java.text.SimpleDateFormat
 import java.util.*
 import javax.imageio.ImageIO
 import javax.servlet.http.HttpServletRequest
@@ -97,27 +98,69 @@
         val requestId = if (clientid == null) appid else "$appid-$clientid"
         return apiClientRepository.findById(requestId).let {
             if (it.isPresent && checkSecretToken(it.get(), secret)) {
-                apiClientRepository.delete(it.get())
+                apiClientRepository.deleteById(requestId)
                 val token = JwtTokenUtil(jwtConfig).generateToken(
                         mapOf("uid" to appid, "issuer" to "payapi",
                                 "audience" to (clientid ?: appid),
                                 "authorities" to it.get().roles.split(";")))
                 JwtRedis().apply {
                     jti = token.jti
+                    uid = appid
                     status = TradeDict.JWT_STATUS_NORMAL
-                    expiration = token.expiration.value
+                    expiration = token.expiration.valueInMillis
                 }.apply {
                     apiJwtRepository.save(this)
                 }
+                val exp = Calendar.getInstance()
+                val fmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z")
+                fmt.timeZone = TimeZone.getTimeZone("UTC")
+                exp.timeInMillis = token.expiration.valueInMillis
                 ResponseEntity.ok(ResponseBodyBuilder.create()
                         .data("jwt", token.jwtToken)
                         .data("appid", appid)
+                        .data("expiredAt", fmt.format(exp.time))
                         .success())
             } else {
                 ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
             }
         }
     }
+
+    @GetMapping("/refresh")
+    fun refresh(@RequestHeader("\${jwt.header}") auth: String): ResponseEntity<Any> {
+        if (!auth.startsWith(jwtConfig.tokenHeader)) {
+            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
+        }
+        val jwt = JwtTokenUtil(jwtConfig).verifyToken(auth.substring(jwtConfig.tokenHeader.length))
+        val appid = jwt["uid"] as String
+        apiClientDao.findById(appid).let {
+            if (it.isPresent && it.get().status == TradeDict.STATUS_NORMAL) {
+                // 新证书
+                val token = JwtTokenUtil(jwtConfig).generateToken(
+                        mapOf("uid" to appid, "issuer" to "payapi",
+                                "audience" to jwt["audience"],
+                                "authorities" to it.get().roles.split(";")))
+                JwtRedis().apply {
+                    jti = token.jti
+                    uid = appid
+                    status = TradeDict.JWT_STATUS_NORMAL
+                    expiration = token.expiration.valueInMillis
+                }.apply {
+                    apiJwtRepository.save(this)
+                }
+                val exp = Calendar.getInstance()
+                val fmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z")
+                fmt.timeZone = TimeZone.getTimeZone("UTC")
+                exp.timeInMillis = token.expiration.valueInMillis
+                ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .data("jwt", token.jwtToken)
+                        .data("appid", appid)
+                        .data("expiredAt", fmt.format(exp.time))
+                        .success())
+            }
+        }
+        return ResponseEntity.ok().build()
+    }
 }
 
 @RestController
diff --git a/src/main/kotlin/com/supwisdom/dlpay/security.kt b/src/main/kotlin/com/supwisdom/dlpay/security.kt
index 20f1207..6a32255 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -57,8 +57,13 @@
     }
 
     override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
-        request.getHeader(jwtConfig.header)?.let { jwt ->
+        request.getHeader(jwtConfig.header)?.let { authHeader ->
             try {
+                val jwt = if (authHeader.startsWith(jwtConfig.tokenHeader)) {
+                    authHeader.substring(jwtConfig.tokenHeader.length)
+                } else {
+                    throw JoseException("JWT Header error")
+                }
                 val claims = getUtil().verifyToken(jwt)
                 apiJwtRepository.findById(claims["jti"].toString()).let {
                     if (!it.isPresent) {