diff --git a/Pinnacle/pom.xml b/Pinnacle/pom.xml
index 8ee37b4..7a8736c 100644
--- a/Pinnacle/pom.xml
+++ b/Pinnacle/pom.xml
@@ -92,6 +92,10 @@
java-jwt
4.3.0
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
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 5898543..5c8bea9 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
@@ -5,6 +5,7 @@ import com.cfive.pinnacle.entity.common.ResponseCode;
import com.cfive.pinnacle.entity.common.ResponseResult;
import com.cfive.pinnacle.service.permission.ILoginService;
import com.cfive.pinnacle.utils.WebUtil;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -28,8 +29,8 @@ public class LoginController {
}
@RequestMapping("/logout")
- public ResponseResult logout() {
- boolean result = loginService.logout();
+ public ResponseResult logout(HttpServletRequest request) {
+ boolean result = loginService.logout(request.getHeader("token"));
if (result) {
return ResponseResult.build(ResponseCode.LOGOUT_SUCCESS, "Logout Success", null);
} else {
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 4ff73df..4c31828 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
@@ -10,6 +10,8 @@ public class ResponseCode {
public static final int LOGIN_USERNAME_PASSWORD_ERROR = 20011;
public static final int LOGOUT_SUCCESS = 20015;
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 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 a083aec..8b53e53 100644
--- a/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java
+++ b/Pinnacle/src/main/java/com/cfive/pinnacle/filter/JwtAuthenticationTokenFilter.java
@@ -1,10 +1,12 @@
package com.cfive.pinnacle.filter;
-import com.auth0.jwt.interfaces.DecodedJWT;
+import com.cfive.pinnacle.entity.common.ResponseCode;
import com.cfive.pinnacle.entity.permission.LoginUser;
import com.cfive.pinnacle.utils.JwtUtil;
import com.cfive.pinnacle.utils.RedisCache;
+import com.cfive.pinnacle.utils.WebUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
+import jakarta.annotation.Nonnull;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@@ -29,26 +31,29 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
}
@Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+ protected void doFilterInternal(HttpServletRequest request, @Nonnull HttpServletResponse response, @Nonnull FilterChain filterChain) throws ServletException, IOException {
String token = request.getHeader("token");
if (!StringUtils.hasText(token)) {
filterChain.doFilter(request, response);
return;
}
- String userId;
try {
- DecodedJWT decodedJWT = JwtUtil.parseJWT(token);
- userId = decodedJWT.getSubject();
+ JwtUtil.parseJWT(token);
} catch (Exception e) {
- throw new RuntimeException("Token is illegal");
+ String objectResponse = WebUtil.objectResponse(ResponseCode.TOKEN_IS_ILLEGAL, "Token is illegal", null);
+ WebUtil.renderString(response, objectResponse);
+ return;
}
- String redisKey = "login:" + userId;
+ String redisKey = "login:" + token;
LoginUser loginUser = new ObjectMapper().convertValue(redisCache.getCacheObject(redisKey), LoginUser.class);
if (Objects.isNull(loginUser)) {
- throw new RuntimeException("Not logged in");
+ String objectResponse = WebUtil.objectResponse(ResponseCode.TOKEN_HAS_EXPIRED, "Token has expired", null);
+ WebUtil.renderString(response, objectResponse);
+ return;
}
+
// Todo 权限
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, null);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/handler/AuthenticationEntryPointHandler.java b/Pinnacle/src/main/java/com/cfive/pinnacle/handler/AuthenticationEntryPointHandler.java
index 30f9231..da63c08 100644
--- a/Pinnacle/src/main/java/com/cfive/pinnacle/handler/AuthenticationEntryPointHandler.java
+++ b/Pinnacle/src/main/java/com/cfive/pinnacle/handler/AuthenticationEntryPointHandler.java
@@ -18,7 +18,7 @@ public class AuthenticationEntryPointHandler implements AuthenticationEntryPoint
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
String objectResponse;
if (authException instanceof BadCredentialsException) {
- objectResponse = WebUtil.objectResponse(ResponseCode.LOGOUT_FAILED, authException.getMessage(), null);
+ objectResponse = WebUtil.objectResponse(ResponseCode.LOGIN_USERNAME_PASSWORD_ERROR, authException.getMessage(), null);
} else if (authException instanceof InsufficientAuthenticationException) {
objectResponse = WebUtil.objectResponse(ResponseCode.UNAUTHORIZED, authException.getMessage(), null);
} else {
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 196eeb5..b791258 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
@@ -7,5 +7,5 @@ import java.util.HashMap;
public interface ILoginService {
HashMap login(User user);
- boolean logout();
+ boolean logout(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 2c8c1ea..96760df 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
@@ -9,11 +9,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
@Service
public class LoginServiceImpl implements ILoginService {
@@ -46,17 +46,13 @@ public class LoginServiceImpl implements ILoginService {
HashMap hashMap = new HashMap<>();
hashMap.put("token", jwt);
- redisCache.setCacheObject("login:" + userId, loginUser);
+ redisCache.setCacheObject("login:" + jwt, loginUser, 10, TimeUnit.MINUTES);
return hashMap;
}
@Override
- public boolean logout() {
- Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
- LoginUser loginUser = (LoginUser) authentication.getPrincipal();
-
- Long userId = loginUser.getUser().getId();
- return redisCache.deleteObject("login:" + userId);
+ public boolean logout(String token) {
+ return redisCache.deleteObject("login:" + token);
}
}
diff --git a/Pinnacle/src/main/java/com/cfive/pinnacle/utils/WebUtil.java b/Pinnacle/src/main/java/com/cfive/pinnacle/utils/WebUtil.java
index 0c9cd53..da62fe1 100644
--- a/Pinnacle/src/main/java/com/cfive/pinnacle/utils/WebUtil.java
+++ b/Pinnacle/src/main/java/com/cfive/pinnacle/utils/WebUtil.java
@@ -1,6 +1,5 @@
package com.cfive.pinnacle.utils;
-import com.cfive.pinnacle.entity.User;
import com.cfive.pinnacle.entity.common.ResponseResult;
import com.cfive.pinnacle.entity.permission.LoginUser;
import com.fasterxml.jackson.core.JsonProcessingException;
diff --git a/ui/src/constants/Common.constants.ts b/ui/src/constants/Common.constants.ts
index 4f949c1..a68a935 100644
--- a/ui/src/constants/Common.constants.ts
+++ b/ui/src/constants/Common.constants.ts
@@ -10,6 +10,31 @@ const SIZE_ICON_MD = '24px'
const SIZE_ICON_LG = '32px'
const SIZE_ICON_XL = '64px'
+// Response Code
+const SYSTEM_OK = 20000
+const LOGIN_SUCCESS = 20010
+const LOGIN_USERNAME_PASSWORD_ERROR = 20011
+const LOGOUT_SUCCESS = 20015
+const LOGOUT_FAILED = 20016
+const TOKEN_IS_ILLEGAL = 20017
+const TOKEN_HAS_EXPIRED = 20018
+const DATABASE_SELECT_OK = 20021
+const DATABASE_SAVE_OK = 20022
+const DATABASE_UPDATE_OK = 20023
+const DATABASE_DELETE_OK = 20024
+const DATABASE_SELECT_ERROR = 20031
+const DATABASE_SAVE_ERROR = 20032
+const DATABASE_UPDATE_ERROR = 20033
+const DATABASE_DELETE_ERROR = 20034
+const DATABASE_TIMEOUT_ERROR = 20035
+const DATABASE_CONNECT_ERROR = 20036
+
+const UNAUTHORIZED = 30010
+const ACCESS_DENIED = 30030
+
+const SYSTEM_ERROR = 50001
+const SYSTEM_TIMEOUT = 50002
+
export {
PRODUCTION_NAME,
TOKEN_NAME,
@@ -21,5 +46,26 @@ export {
SIZE_ICON_SM,
SIZE_ICON_MD,
SIZE_ICON_LG,
- SIZE_ICON_XL
+ SIZE_ICON_XL,
+ SYSTEM_OK,
+ LOGIN_SUCCESS,
+ LOGIN_USERNAME_PASSWORD_ERROR,
+ LOGOUT_SUCCESS,
+ LOGOUT_FAILED,
+ TOKEN_IS_ILLEGAL,
+ TOKEN_HAS_EXPIRED,
+ DATABASE_SELECT_OK,
+ DATABASE_SAVE_OK,
+ DATABASE_UPDATE_OK,
+ DATABASE_DELETE_OK,
+ DATABASE_SELECT_ERROR,
+ DATABASE_SAVE_ERROR,
+ DATABASE_UPDATE_ERROR,
+ DATABASE_DELETE_ERROR,
+ DATABASE_TIMEOUT_ERROR,
+ DATABASE_CONNECT_ERROR,
+ UNAUTHORIZED,
+ ACCESS_DENIED,
+ SYSTEM_ERROR,
+ SYSTEM_TIMEOUT
}
diff --git a/ui/src/main.ts b/ui/src/main.ts
index c09550d..50220f9 100644
--- a/ui/src/main.ts
+++ b/ui/src/main.ts
@@ -5,6 +5,8 @@ import router from '@/router'
import '@/assets/css/base.css'
import '@/assets/css/common.css'
+import 'element-plus/theme-chalk/el-message.css'
+
const app = createApp(App)
app.use(router).mount('#app')
diff --git a/ui/src/pages/Login.vue b/ui/src/pages/Login.vue
index b6a6e8a..349d885 100644
--- a/ui/src/pages/Login.vue
+++ b/ui/src/pages/Login.vue
@@ -80,8 +80,8 @@
import { getCaptchaSrc, login, verifyCaptcha } from '@/utils/auth'
import backShape from '@/assets/svg/back-shape.svg'
import { ElMessage } from 'element-plus'
-import 'element-plus/theme-chalk/el-message.css'
-import { PRODUCTION_NAME } from '@/constants/Common.constants'
+import { LOGIN_SUCCESS, PRODUCTION_NAME } from '@/constants/Common.constants'
+import { setToken } from '@/utils/common'
export default {
name: 'LoginPage',
@@ -102,7 +102,8 @@ export default {
getNewCaptcha() {
this.captchaSrc = getCaptchaSrc()
},
- async login() {
+ login() {
+ const _this = this
if (!this.userName) {
ElMessage.error({
dangerouslyUseHTMLString: true,
@@ -131,22 +132,25 @@ export default {
})
return
}
- if (await login(this.userName, this.password)) {
- ElMessage.success({
- dangerouslyUseHTMLString: true,
- message: '登录成功'
- })
- this.loggingIn = true
- const _this = this
- setTimeout(function () {
- _this.$router.push('/')
- }, 1500)
- } else {
- ElMessage.error({
- dangerouslyUseHTMLString: true,
- message: '用户名 或 密码 错误'
- })
- }
+ login(this.userName, this.password).then((res) => {
+ const data = res.data
+ if (data.code === LOGIN_SUCCESS) {
+ setToken(data.data.token)
+ ElMessage.success({
+ dangerouslyUseHTMLString: true,
+ message: '登录成功'
+ })
+ this.loggingIn = true
+ setTimeout(function () {
+ _this.$router.push('/')
+ }, 1500)
+ } else {
+ ElMessage.error({
+ dangerouslyUseHTMLString: true,
+ message: '用户名 或 密码 错误'
+ })
+ }
+ })
}
}
}
diff --git a/ui/src/pages/Main.vue b/ui/src/pages/Main.vue
index 54d4a0d..efd8e42 100644
--- a/ui/src/pages/Main.vue
+++ b/ui/src/pages/Main.vue
@@ -156,6 +156,7 @@ import {
} from '@/constants/Common.constants.js'
import _ from 'lodash'
import { getUsername, logout } from '@/utils/auth'
+import { ElMessage } from 'element-plus'
export default {
name: 'MainFrame',
@@ -187,7 +188,13 @@ export default {
},
logout() {
logout()
- this.$router.push({ name: 'Login' })
+ ElMessage.success({
+ dangerouslyUseHTMLString: true,
+ message: '退出登录'
+ })
+ setTimeout(() => {
+ this.$router.push({ name: 'Login' })
+ }, 1500)
}
},
mounted() {
diff --git a/ui/src/services/index.ts b/ui/src/services/index.ts
index 8813f04..6a338c7 100644
--- a/ui/src/services/index.ts
+++ b/ui/src/services/index.ts
@@ -1,6 +1,8 @@
import axios, { type AxiosError } from 'axios'
-import { getToken, removeToken } from '@/utils/common'
+import { clearLocalStorage, getToken } from '@/utils/common'
import router from '@/router'
+import { TOKEN_HAS_EXPIRED, TOKEN_IS_ILLEGAL, UNAUTHORIZED } from '@/constants/Common.constants'
+import { ElMessage } from 'element-plus'
const service = axios.create({
baseURL: 'http://localhost:8621',
@@ -23,17 +25,26 @@ service.interceptors.request.use(
service.interceptors.response.use(
(response) => {
+ switch (response.data.code) {
+ case UNAUTHORIZED:
+ case TOKEN_IS_ILLEGAL:
+ case TOKEN_HAS_EXPIRED:
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ console.log(`request error: ${response.data.code} - ${response.data.msg}`)
+ clearLocalStorage()
+ ElMessage.error({
+ dangerouslyUseHTMLString: true,
+ message: '登录已过期'
+ })
+ setTimeout(function () {
+ void router.push({ name: 'Login' })
+ }, 1500)
+ }
return response
},
async (error) => {
if (error.response != null) {
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- console.log(`request error: ${error.response.code} - ${error.response.msg}`)
- switch (error.response.code) {
- case 30010:
- removeToken()
- await router.push({ name: 'Login' })
- }
+ /* empty */
}
return await Promise.reject(error?.response?.data)
}
diff --git a/ui/src/utils/auth.ts b/ui/src/utils/auth.ts
index 6495edb..4e5bda1 100644
--- a/ui/src/utils/auth.ts
+++ b/ui/src/utils/auth.ts
@@ -1,33 +1,19 @@
import type { Captcha } from './common'
-import {
- getCaptcha,
- getLocalStorage,
- getToken,
- removeLocalStorage,
- setLocalStorage,
- setToken
-} from './common'
+import { clearLocalStorage, getCaptcha, getLocalStorage, setLocalStorage } from './common'
import { TOKEN_NAME } from '@/constants/Common.constants'
import _ from 'lodash'
import request from '@/services'
let captcha: Captcha
-async function login(username: string, passwd: string): Promise {
- removeLocalStorage('username')
- await request.post('/login', { username, passwd }).then((res: any) => {
- const response = res.data
- if (response.code === 20010) {
- setToken(response.data.token)
- }
- })
-
- return !_.isEmpty(getToken())
+async function login(username: string, passwd: string): Promise {
+ return await request.post('/login', { username, passwd })
}
function logout(): void {
- removeLocalStorage(TOKEN_NAME)
- removeLocalStorage('username')
+ void request.get('/logout').finally(() => {
+ clearLocalStorage()
+ })
}
function getLoginStatus(): boolean {
diff --git a/ui/src/utils/common.ts b/ui/src/utils/common.ts
index d37d57c..fd1182f 100644
--- a/ui/src/utils/common.ts
+++ b/ui/src/utils/common.ts
@@ -77,6 +77,10 @@ function removeToken(): void {
removeLocalStorage(TOKEN_NAME)
}
+function clearLocalStorage(): void {
+ localStorage.clear()
+}
+
function randomInt(start: number, end: number): number {
if (start > end) {
const t = start
@@ -149,5 +153,6 @@ export {
removeCookie,
removeLocalStorage,
removeToken,
+ clearLocalStorage,
getCaptcha
}