diff --git a/kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/kiccTokenEndpoint.java b/kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/KiccTokenEndpoint.java similarity index 85% rename from kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/kiccTokenEndpoint.java rename to kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/KiccTokenEndpoint.java index 6b6f56e8..69159b91 100644 --- a/kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/kiccTokenEndpoint.java +++ b/kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/KiccTokenEndpoint.java @@ -14,6 +14,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.cache.CacheManager; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpHeaders; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.event.LogoutSuccessEvent; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2RefreshToken; @@ -44,7 +45,7 @@ import java.util.stream.Collectors; @RestController @RequiredArgsConstructor @RequestMapping("/token") -public class kiccTokenEndpoint { +public class KiccTokenEndpoint { private final ClientDetailsService clientDetailsService; @@ -98,11 +99,19 @@ public class kiccTokenEndpoint { @DeleteMapping("/logout") public R logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) { if (StrUtil.isBlank(authHeader)) { - return R.ok(); + return R.error("退出失败,token 为空"); } - String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StrUtil.EMPTY).trim(); - return removeToken(tokenValue); + OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue); + if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) { + return R.error("退出失败,token 无效"); + } + // 清空access token + tokenStore.removeAccessToken(accessToken); + // 清空 refresh token + OAuth2RefreshToken refreshToken = accessToken.getRefreshToken(); + tokenStore.removeRefreshToken(refreshToken); + return R.ok(); } /** @@ -111,21 +120,22 @@ public class kiccTokenEndpoint { */ @Inner @DeleteMapping("/{token}") + @PreAuthorize("@ps.hasPerm('token_del')") public R removeToken(@PathVariable("token") String token) { - OAuth2AccessToken accessToken = tokenStore.readAccessToken(token); - if (accessToken == null || StrUtil.isBlank(accessToken.getValue())) { - return R.ok(); + OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(token); + if (oAuth2AccessToken == null || StrUtil.isBlank(oAuth2AccessToken.getValue())) { + return R.ok(Boolean.TRUE, "操作失败,token 无效"); } - OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(accessToken); + OAuth2Authentication auth2Authentication = tokenStore.readAuthentication(oAuth2AccessToken); // 清空用户信息 cacheManager.getCache(CacheConstants.USER_DETAILS).evict(auth2Authentication.getName()); // 清空access token - tokenStore.removeAccessToken(accessToken); + tokenStore.removeAccessToken(oAuth2AccessToken); // 清空 refresh token - OAuth2RefreshToken refreshToken = accessToken.getRefreshToken(); + OAuth2RefreshToken refreshToken = oAuth2AccessToken.getRefreshToken(); tokenStore.removeRefreshToken(refreshToken); // 处理自定义退出事件,保存相关日志 @@ -140,9 +150,10 @@ public class kiccTokenEndpoint { */ @Inner @PostMapping("/list") + @PreAuthorize("@ps.hasPerm('token_view')") public R tokenList(@RequestBody Map params) { // 根据分页参数获取对应数据 - String key = String.format("%sauth_to_access:*", CacheConstants.OAUTH_ACCESS); + String key = String.format("%south_to_access:*", CacheConstants.OAUTH_ACCESS); int current = MapUtil.getInt(params, CommonConstants.CURRENT); int size = MapUtil.getInt(params, CommonConstants.SIZE); Set keys = redisTemplate.keys(key); diff --git a/kicc-ui/.env b/kicc-ui/.env index d52956f4..12ca17e2 100644 --- a/kicc-ui/.env +++ b/kicc-ui/.env @@ -12,3 +12,6 @@ VITE_GLOB_CLIENT_ID = kicc # client-secret VITE_GLOB_CLIENT_SECRET = kicc + +# 网关ase密码解密密钥,保持跟后端密钥一致,必须要有否则登录会失败的 +VITE_GLOB_GATEWAY_ASE_ENCODE_SECRET = changsha-kanglai diff --git a/kicc-ui/src/api/controller/sys/user.ts b/kicc-ui/src/api/controller/sys/user.ts index efca2638..908ae4ab 100644 --- a/kicc-ui/src/api/controller/sys/user.ts +++ b/kicc-ui/src/api/controller/sys/user.ts @@ -3,21 +3,22 @@ import {GetCaptchaModel, GetUserInfoModel, LoginParams, LoginResultModel,} from import {encryptionLogin} from '/@/utils/cipher'; import qs from 'qs'; import {RequestOptions} from "/#/axios"; +import {useGlobSetting} from "/@/hooks/setting"; +const globSetting = useGlobSetting(); enum Api { - Login = '/auth_proxy/oauth/token', - Logout = '/mate-uaa/auth/logout', - GetUserInfo = '/system_proxy/system/user/info', - GetPermCode = '/getPermCode', - GetCaptcha = '/code', + login = '/auth_proxy/oauth/token', + logout = '/auth_proxy/token/logout', + getUserInfo = '/system_proxy/system/user/info', + getCaptcha = '/code', } /** 用户登录接口 */ -export function loginApi(params: LoginParams, options?: boolean | RequestOptions) { +export function login(params: LoginParams, options?: boolean | RequestOptions) { // 非对称密钥ASE加密处理 const user = encryptionLogin({ data: params, - key: 'changsha-kanglai', + key: globSetting.gatewayAseEncodeSecret, param: ['password'] }); @@ -30,7 +31,7 @@ export function loginApi(params: LoginParams, options?: boolean | RequestOptions const data = qs.stringify({'username': username, 'password': password}); return defHttp.post({ - url: Api.Login, + url: Api.login, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' }, @@ -39,21 +40,17 @@ export function loginApi(params: LoginParams, options?: boolean | RequestOptions }, options); } -/** - * @description: getUserInfo - */ +/** 获取当前用户信息 */ export function getUserInfo() { - return defHttp.get({ url: Api.GetUserInfo }); + return defHttp.get({ url: Api.getUserInfo }); } -export function getPermCode() { - return defHttp.get({ url: Api.GetPermCode }); -} - -export function doLogout() { - return defHttp.post({ url: Api.Logout }); +/** 登出 */ +export function logout() { + return defHttp.delete({ url: Api.logout }); } +/** 获取验证码 */ export function getCaptcha() { - return defHttp.get({ url: `${Api.GetCaptcha}?key=${Date.now()}` }); + return defHttp.get({ url: `${Api.getCaptcha}?key=${Date.now()}` }); } diff --git a/kicc-ui/src/api/controller/system/menu.ts b/kicc-ui/src/api/controller/system/menu.ts index 84f3e115..7ccba131 100644 --- a/kicc-ui/src/api/controller/system/menu.ts +++ b/kicc-ui/src/api/controller/system/menu.ts @@ -16,20 +16,20 @@ enum Api { roleMenuIds = '/system_proxy/system/menu/roleMenuTree' } -// 查询菜单列表 +/** 查询菜单列表 */ export const listMenu = (params?: Partial) => defHttp.get({ url: Api.list, params }); -// 新增菜单 +/** 新增菜单 */ export const addMenu = (params: Partial) => defHttp.post({ url: Api.add, data: params }); -// 修改菜单 +/** 修改菜单 */ export const editMenu = (params: Partial) => defHttp.put({ url: Api.edit, data: params }); -// 查询菜单详细 +/** 查询菜单详细 */ export const getMenu = (id: string) => defHttp.get({ url: `${Api.get}/${id}` }); -// 删除菜单 +/** 删除菜单 */ export const delMenu = (id: string) => defHttp.delete({ url: `${Api.del}/${id}` }); -// 通过角色编号查询菜单编号 +/** 通过角色编号查询菜单编号 */ export const getRoleMenuIds = (roleId : string) => defHttp.get>({ url: `${Api.roleMenuIds}/${roleId}`}); diff --git a/kicc-ui/src/api/controller/system/role.ts b/kicc-ui/src/api/controller/system/role.ts index 4a4fff49..17a3e54e 100644 --- a/kicc-ui/src/api/controller/system/role.ts +++ b/kicc-ui/src/api/controller/system/role.ts @@ -15,20 +15,20 @@ enum Api { changeStatus = '/system_proxy/system/role/changeStatus' } -// 查询角色列表 +/** 查询角色列表 */ export const listRole = (params?: Partial) => defHttp.get({ url: Api.list, params }, { isReturnResultResponse: true }); -// 新增角色 +/** 新增角色 */ export const addRole = (params: Partial) => defHttp.post({ url: Api.add, data: params }); -// 修改角色 +/** 修改角色 */ export const editRole = (params: Partial) => defHttp.put({ url: Api.edit, data: params }); -// 查询角色详细 +/** 查询角色详细 */ export const getRole = (id: string) => defHttp.get({ url: `${Api.get}/${id}` }); -// 删除角色 +/** 删除角色 */ export const delRole = (id: string) => defHttp.delete({ url: `${Api.del}/${id}` }); -// 修改角色状态 +/** 修改角色状态 */ export const changeStatus = (id: string, status: string) => defHttp.put({ url: Api.changeStatus, data: { id: id, status: status } }); diff --git a/kicc-ui/src/api/controller/system/user.ts b/kicc-ui/src/api/controller/system/user.ts index cf22e743..429a4392 100644 --- a/kicc-ui/src/api/controller/system/user.ts +++ b/kicc-ui/src/api/controller/system/user.ts @@ -18,26 +18,26 @@ enum Api { changeStatus='/system_proxy/system/user/changeStatus' } -// 查询用户列表 +/** 查询用户列表 */ export const listUser = (params?: Partial) => defHttp.get({ url: Api.list, params }, { isReturnResultResponse: true }); -// 新增用户 +/** 新增用户 */ export const addUser = (params: Partial) => defHttp.post({ url: Api.add, data: params }); -// 修改用户 +/** 修改用户 */ export const editUser = (params: Partial) => defHttp.put({ url: Api.edit, data: params }); -// 查询用户详细 +/** 查询用户详细 */ export const getUser = (id: string) => defHttp.get>({ url: `${Api.get}/${id}` }); -// 删除用户 +/** 删除用户 */ export const delUser = (id: string) => defHttp.delete({ url: `${Api.del}/${id}` }); -// 更新密码 +/** 更新密码 */ export const updatePwd = (params: Partial) => defHttp.put({ url: Api.updatePwd, params }); -// 重置密码 +/** 重置密码 */ export const resetPwd = (params: Partial) => defHttp.put({ url: Api.resetPwd, data: params }); -// 修改用户状态 +/** 修改用户状态 */ export const changeStatus = (id: string, status: string) => defHttp.put({ url: Api.changeStatus, data: { id: id, status: status } }); diff --git a/kicc-ui/src/hooks/setting/index.ts b/kicc-ui/src/hooks/setting/index.ts index fa1ab96b..a8c36a16 100644 --- a/kicc-ui/src/hooks/setting/index.ts +++ b/kicc-ui/src/hooks/setting/index.ts @@ -18,6 +18,7 @@ export const useGlobSetting = (): Readonly => { VITE_GLOB_UPLOAD_URL, VITE_GLOB_CLIENT_ID, VITE_GLOB_CLIENT_SECRET, + VITE_GLOB_GATEWAY_ASE_ENCODE_SECRET } = getAppEnvConfig(); if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) { @@ -33,6 +34,7 @@ export const useGlobSetting = (): Readonly => { uploadUrl: VITE_GLOB_UPLOAD_URL, clientId: VITE_GLOB_CLIENT_ID, clientSecret: VITE_GLOB_CLIENT_SECRET, + gatewayAseEncodeSecret: VITE_GLOB_GATEWAY_ASE_ENCODE_SECRET }; return glob as Readonly; }; diff --git a/kicc-ui/src/store/modules/user.ts b/kicc-ui/src/store/modules/user.ts index a03c15a1..1e4ad263 100644 --- a/kicc-ui/src/store/modules/user.ts +++ b/kicc-ui/src/store/modules/user.ts @@ -12,7 +12,7 @@ import {PageEnum} from '/@/enums/pageEnum'; import {ACCESS_TOKEN_KEY, PERMISSIONS_KEY, REFRESH_TOKEN_KEY, ROLE_IDS_KEY, USER_INFO_KEY} from '/@/enums/cacheEnum'; import {getAuthCache, setAuthCache} from '/@/utils/auth'; import {GetUserInfoModel, LoginParams} from '/@/api/controller/sys/model/userModel'; -import {doLogout, getUserInfo, loginApi} from '/@/api/controller/sys/user'; +import {logout, getUserInfo, login} from '/@/api/controller/sys/user'; import {useI18n} from '/@/hooks/web/useI18n'; import {useMessage} from '/@/hooks/web/useMessage'; import {router} from '/@/router'; @@ -101,7 +101,7 @@ export const useUserStore = defineStore({ async login(params: LoginParams & { goHome?: boolean; unLock?: boolean; }): Promise { try { const { goHome = true, unLock = false, ...loginParams } = params; - const data = await loginApi(loginParams, unLock && { + const data = await login(loginParams, unLock && { // 使用微服务提供的锁屏专属客户端不需要写验证码进行登录 clientId: 'kicc_lock', clientSecret: 'kicc_lock' @@ -144,7 +144,7 @@ export const useUserStore = defineStore({ /** 登出 */ async logout(goLogin = false) { try { - await doLogout(); + await logout(); } catch { console.log('注销Token失败'); } diff --git a/kicc-ui/src/utils/env.ts b/kicc-ui/src/utils/env.ts index 76930c1e..d358f600 100644 --- a/kicc-ui/src/utils/env.ts +++ b/kicc-ui/src/utils/env.ts @@ -36,6 +36,7 @@ export function getAppEnvConfig() { VITE_GLOB_UPLOAD_URL, VITE_GLOB_CLIENT_ID, VITE_GLOB_CLIENT_SECRET, + VITE_GLOB_GATEWAY_ASE_ENCODE_SECRET } = ENV; if (!/^[a-zA-Z\_]*$/.test(VITE_GLOB_APP_SHORT_NAME)) { @@ -52,6 +53,7 @@ export function getAppEnvConfig() { VITE_GLOB_UPLOAD_URL, VITE_GLOB_CLIENT_ID, VITE_GLOB_CLIENT_SECRET, + VITE_GLOB_GATEWAY_ASE_ENCODE_SECRET }; } diff --git a/kicc-ui/types/config.d.ts b/kicc-ui/types/config.d.ts index 7158666b..a23cba0e 100644 --- a/kicc-ui/types/config.d.ts +++ b/kicc-ui/types/config.d.ts @@ -151,6 +151,8 @@ export interface GlobConfig { clientId: string; // clientSecret clientSecret: string; + // 网关ase密码解密密钥,保持跟后端密钥一致,必须要有否则登录会失败的 + gatewayAseEncodeSecret: string; } export interface GlobEnvConfig { @@ -168,4 +170,6 @@ export interface GlobEnvConfig { VITE_GLOB_CLIENT_ID: string; // clientSecret VITE_GLOB_CLIENT_SECRET: string; + // 网关ase密码解密密钥,保持跟后端密钥一致,必须要有否则登录会失败的 + VITE_GLOB_GATEWAY_ASE_ENCODE_SECRET: string; }