diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/controller/permission/LoginController.java b/Pinnacle/src/main/java/com/cfive/pinnacle/controller/permission/LoginController.java index 4e248c4..fe35d63 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/controller/permission/LoginController.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/controller/permission/LoginController.java @@ -28,7 +28,7 @@ public class LoginController { @PostMapping("/login") public ResponseResult> login(@RequestBody User user) { HashMap hashMap = loginService.login(user); - return ResponseResult.build(ResponseCode.LOGIN_SUCCESS, "Login Success", hashMap); + return ResponseResult.build(ResponseCode.LOGIN_SUCCESS, "Login success", hashMap); } @Operation(summary = "登出") @@ -36,9 +36,17 @@ public class LoginController { public ResponseResult logout(HttpServletRequest request) { boolean result = loginService.logout(request.getHeader("token")); if (result) { - return ResponseResult.build(ResponseCode.LOGOUT_SUCCESS, "Logout Success", null); + return ResponseResult.build(ResponseCode.LOGOUT_SUCCESS, "Logout success", null); } else { - return ResponseResult.build(ResponseCode.LOGOUT_FAILED, "Logout Failed", null); + return ResponseResult.build(ResponseCode.LOGOUT_FAILED, "Logout failed", null); } } + + @Operation(summary = "更新 Token") + @GetMapping("/token") + public ResponseResult> renewToken(HttpServletRequest request) { + String token = request.getHeader("token"); + HashMap hashMap = loginService.renewToken(token); + return ResponseResult.build(ResponseCode.TOKEN_RENEW_SUCCESS, "Token renew success", hashMap); + } } diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/entity/common/ResponseCode.java b/Pinnacle/src/main/java/com/cfive/pinnacle/entity/common/ResponseCode.java index e9dd3ba..7ac5a91 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/entity/common/ResponseCode.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/entity/common/ResponseCode.java @@ -12,6 +12,7 @@ public class ResponseCode { public static final int LOGOUT_FAILED = 20016; public static final int TOKEN_IS_ILLEGAL = 20017; public static final int TOKEN_HAS_EXPIRED = 20018; + public static final int TOKEN_RENEW_SUCCESS = 20019; public static final int DATABASE_SELECT_OK = 20021; public static final int DATABASE_SAVE_OK = 20022; public static final int DATABASE_UPDATE_OK = 20023; diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java b/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java index 59b918d..d2cdd77 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java @@ -19,6 +19,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; import java.util.Objects; +import java.util.concurrent.TimeUnit; @Component public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @@ -45,6 +46,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { if (Objects.isNull(loginUser)) { throw new TokenHasExpiredException(); } + redisCache.expire(redisKey, 20, TimeUnit.MINUTES); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authenticationToken); diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/ILoginService.java b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/ILoginService.java index c155395..7ef79f6 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/ILoginService.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/ILoginService.java @@ -8,4 +8,6 @@ public interface ILoginService { HashMap login(User user); boolean logout(String token); + + HashMap renewToken(String token); } diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java index 0bc3320..f921ab6 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/service/permission/impl/LoginServiceImpl.java @@ -5,6 +5,7 @@ import com.cfive.pinnacle.entity.permission.LoginUser; import com.cfive.pinnacle.service.permission.ILoginService; import com.cfive.pinnacle.utils.JwtUtil; import com.cfive.pinnacle.utils.RedisCache; +import com.cfive.pinnacle.utils.WebUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -46,7 +47,7 @@ public class LoginServiceImpl implements ILoginService { HashMap hashMap = new HashMap<>(); hashMap.put("token", jwt); - redisCache.setCacheObject("login:" + jwt, loginUser, 30, TimeUnit.MINUTES); + redisCache.setCacheObject("login:" + jwt, loginUser, 20, TimeUnit.MINUTES); return hashMap; } @@ -55,4 +56,15 @@ public class LoginServiceImpl implements ILoginService { public boolean logout(String token) { return redisCache.deleteObject("login:" + token); } + + @Override + public HashMap renewToken(String token) { + String oldRedisKey = "login:" + token; + redisCache.deleteObject(oldRedisKey); + String jwt = JwtUtil.createJWT(WebUtil.getLoginUser().getUser().getId().toString()); + HashMap hashMap = new HashMap<>(); + hashMap.put("token", jwt); + redisCache.setCacheObject("login:" + jwt, WebUtil.getLoginUser(), 20, TimeUnit.MINUTES); + return hashMap; + } } diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/utils/JwtUtil.java b/Pinnacle/src/main/java/com/cfive/pinnacle/utils/JwtUtil.java index ea93b85..af6e871 100644 --- a/Pinnacle/src/main/java/com/cfive/pinnacle/utils/JwtUtil.java +++ b/Pinnacle/src/main/java/com/cfive/pinnacle/utils/JwtUtil.java @@ -17,7 +17,7 @@ import java.util.UUID; public class JwtUtil { // 有效期 - public static final Long JWT_TTL = 60 * 60 * 1000L; // 60 * 60 * 1000 一个小时 + public static final Long JWT_TTL = 2 * 60 * 60 * 1000L; // 2 * 60 * 60 * 1000 两个小时 // 秘钥明文 public static final String JWT_KEY = "pinnacle"; //签发者 diff --git a/ui/src/constants/Common.constants.ts b/ui/src/constants/Common.constants.ts index c66d2aa..2ecd1af 100644 --- a/ui/src/constants/Common.constants.ts +++ b/ui/src/constants/Common.constants.ts @@ -19,6 +19,7 @@ const LOGOUT_SUCCESS = 20015 const LOGOUT_FAILED = 20016 const TOKEN_IS_ILLEGAL = 20017 const TOKEN_HAS_EXPIRED = 20018 +const TOKEN_RENEW_SUCCESS = 20019 const DATABASE_SELECT_OK = 20021 const DATABASE_SAVE_OK = 20022 const DATABASE_UPDATE_OK = 20023 @@ -59,6 +60,7 @@ export { LOGOUT_FAILED, TOKEN_IS_ILLEGAL, TOKEN_HAS_EXPIRED, + TOKEN_RENEW_SUCCESS, DATABASE_SELECT_OK, DATABASE_SAVE_OK, DATABASE_UPDATE_OK, diff --git a/ui/src/pages/Login.vue b/ui/src/pages/Login.vue index 6eebe5a..9b91381 100644 --- a/ui/src/pages/Login.vue +++ b/ui/src/pages/Login.vue @@ -155,10 +155,10 @@ export default { return } login(this.userName, this.password).then((res) => { - const data = res.data - switch (data.code) { + const response = res.data + switch (response.code) { case LOGIN_SUCCESS: - setToken(data.data.token) + setToken(response.data.token) ElMessage.success({ dangerouslyUseHTMLString: true, message: '登录成功' diff --git a/ui/src/services/index.ts b/ui/src/services/index.ts index 522678b..387d657 100644 --- a/ui/src/services/index.ts +++ b/ui/src/services/index.ts @@ -1,5 +1,6 @@ import axios, { type AxiosError } from 'axios' -import { clearLocalStorage, getToken } from '@/utils/common' +import jwtDecode from 'jwt-decode' +import { clearLocalStorage, getToken, setToken } from '@/utils/common' import router from '@/router' import { ACCESS_DENIED, @@ -7,6 +8,7 @@ import { DATABASE_DATA_VALIDATION_FAILED, TOKEN_HAS_EXPIRED, TOKEN_IS_ILLEGAL, + TOKEN_RENEW_SUCCESS, UNAUTHORIZED } from '@/constants/Common.constants' import { ElMessage } from 'element-plus' @@ -18,9 +20,27 @@ const service = axios.create({ }) service.interceptors.request.use( - (config) => { - const token = getToken() + async (config) => { + let token = getToken() if (token != null) { + const jwt = jwtDecode(token) + if ( + (jwt as any).exp * 1000 - new Date().getTime() < 1200000 && + (jwt as any).exp * 1000 - new Date().getTime() > 0 + ) { + await axios + .get('http://localhost:8621/token', { + headers: { token } + }) + .then((res) => { + const response = res.data + if (response.code === TOKEN_RENEW_SUCCESS) { + setToken(response.data.token) + } + }) + } + + token = getToken() config.headers.set('token', token) } return config