Browse Source

👣 完成用户登录功能

master
wangxiang 3 years ago
parent
commit
580f7985f5
  1. 33
      kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/KiccTokenEndpoint.java
  2. 3
      kicc-ui/.env
  3. 35
      kicc-ui/src/api/controller/sys/user.ts
  4. 12
      kicc-ui/src/api/controller/system/menu.ts
  5. 12
      kicc-ui/src/api/controller/system/role.ts
  6. 16
      kicc-ui/src/api/controller/system/user.ts
  7. 2
      kicc-ui/src/hooks/setting/index.ts
  8. 6
      kicc-ui/src/store/modules/user.ts
  9. 2
      kicc-ui/src/utils/env.ts
  10. 4
      kicc-ui/types/config.d.ts

33
kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/kiccTokenEndpoint.java → kicc-auth/src/main/java/com/cloud/kicc/auth/endpoint/KiccTokenEndpoint.java

@ -14,6 +14,7 @@ import lombok.extern.slf4j.Slf4j; @@ -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; @@ -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 { @@ -98,11 +99,19 @@ public class kiccTokenEndpoint {
@DeleteMapping("/logout")
public R<Boolean> 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 { @@ -111,21 +120,22 @@ public class kiccTokenEndpoint {
*/
@Inner
@DeleteMapping("/{token}")
@PreAuthorize("@ps.hasPerm('token_del')")
public R<Boolean> 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 { @@ -140,9 +150,10 @@ public class kiccTokenEndpoint {
*/
@Inner
@PostMapping("/list")
@PreAuthorize("@ps.hasPerm('token_view')")
public R tokenList(@RequestBody Map<String, Object> 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<String> keys = redisTemplate.keys(key);

3
kicc-ui/.env

@ -12,3 +12,6 @@ VITE_GLOB_CLIENT_ID = kicc @@ -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

35
kicc-ui/src/api/controller/sys/user.ts

@ -3,21 +3,22 @@ import {GetCaptchaModel, GetUserInfoModel, LoginParams, LoginResultModel,} from @@ -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 @@ -30,7 +31,7 @@ export function loginApi(params: LoginParams, options?: boolean | RequestOptions
const data = qs.stringify({'username': username, 'password': password});
return defHttp.post<LoginResultModel>({
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 @@ -39,21 +40,17 @@ export function loginApi(params: LoginParams, options?: boolean | RequestOptions
}, <RequestOptions>options);
}
/**
* @description: getUserInfo
*/
/** 获取当前用户信息 */
export function getUserInfo() {
return defHttp.get<GetUserInfoModel>({ url: Api.GetUserInfo });
return defHttp.get<GetUserInfoModel>({ url: Api.getUserInfo });
}
export function getPermCode() {
return defHttp.get<string[]>({ 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<GetCaptchaModel>({ url: `${Api.GetCaptcha}?key=${Date.now()}` });
return defHttp.get<GetCaptchaModel>({ url: `${Api.getCaptcha}?key=${Date.now()}` });
}

12
kicc-ui/src/api/controller/system/menu.ts

@ -16,20 +16,20 @@ enum Api { @@ -16,20 +16,20 @@ enum Api {
roleMenuIds = '/system_proxy/system/menu/roleMenuTree'
}
// 查询菜单列表
/** 查询菜单列表 */
export const listMenu = (params?: Partial<MenuDto>) => defHttp.get({ url: Api.list, params });
// 新增菜单
/** 新增菜单 */
export const addMenu = (params: Partial<Menu>) => defHttp.post({ url: Api.add, data: params });
// 修改菜单
/** 修改菜单 */
export const editMenu = (params: Partial<Menu>) => defHttp.put({ url: Api.edit, data: params });
// 查询菜单详细
/** 查询菜单详细 */
export const getMenu = (id: string) => defHttp.get<Menu>({ url: `${Api.get}/${id}` });
// 删除菜单
/** 删除菜单 */
export const delMenu = (id: string) => defHttp.delete({ url: `${Api.del}/${id}` });
// 通过角色编号查询菜单编号
/** 通过角色编号查询菜单编号 */
export const getRoleMenuIds = (roleId : string) => defHttp.get<ResultVo<any>>({ url: `${Api.roleMenuIds}/${roleId}`});

12
kicc-ui/src/api/controller/system/role.ts

@ -15,20 +15,20 @@ enum Api { @@ -15,20 +15,20 @@ enum Api {
changeStatus = '/system_proxy/system/role/changeStatus'
}
// 查询角色列表
/** 查询角色列表 */
export const listRole = (params?: Partial<RoleDto>) => defHttp.get<RoleVo>({ url: Api.list, params }, { isReturnResultResponse: true });
// 新增角色
/** 新增角色 */
export const addRole = (params: Partial<Role>) => defHttp.post({ url: Api.add, data: params });
// 修改角色
/** 修改角色 */
export const editRole = (params: Partial<Role>) => defHttp.put({ url: Api.edit, data: params });
// 查询角色详细
/** 查询角色详细 */
export const getRole = (id: string) => defHttp.get<Role>({ 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 } });

16
kicc-ui/src/api/controller/system/user.ts

@ -18,26 +18,26 @@ enum Api { @@ -18,26 +18,26 @@ enum Api {
changeStatus='/system_proxy/system/user/changeStatus'
}
// 查询用户列表
/** 查询用户列表 */
export const listUser = (params?: Partial<UserDto>) => defHttp.get<UserVo>({ url: Api.list, params }, { isReturnResultResponse: true });
// 新增用户
/** 新增用户 */
export const addUser = (params: Partial<User>) => defHttp.post({ url: Api.add, data: params });
// 修改用户
/** 修改用户 */
export const editUser = (params: Partial<User>) => defHttp.put({ url: Api.edit, data: params });
// 查询用户详细
/** 查询用户详细 */
export const getUser = (id: string) => defHttp.get<ResultVo<any>>({ url: `${Api.get}/${id}` });
// 删除用户
/** 删除用户 */
export const delUser = (id: string) => defHttp.delete({ url: `${Api.del}/${id}` });
// 更新密码
/** 更新密码 */
export const updatePwd = (params: Partial<User>) => defHttp.put({ url: Api.updatePwd, params });
// 重置密码
/** 重置密码 */
export const resetPwd = (params: Partial<User>) => defHttp.put({ url: Api.resetPwd, data: params });
// 修改用户状态
/** 修改用户状态 */
export const changeStatus = (id: string, status: string) => defHttp.put({ url: Api.changeStatus, data: { id: id, status: status } });

2
kicc-ui/src/hooks/setting/index.ts

@ -18,6 +18,7 @@ export const useGlobSetting = (): Readonly<GlobConfig> => { @@ -18,6 +18,7 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
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<GlobConfig> => { @@ -33,6 +34,7 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
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<GlobConfig>;
};

6
kicc-ui/src/store/modules/user.ts

@ -12,7 +12,7 @@ import {PageEnum} from '/@/enums/pageEnum'; @@ -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({ @@ -101,7 +101,7 @@ export const useUserStore = defineStore({
async login(params: LoginParams & { goHome?: boolean; unLock?: boolean; }): Promise<GetUserInfoModel | null> {
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({ @@ -144,7 +144,7 @@ export const useUserStore = defineStore({
/** 登出 */
async logout(goLogin = false) {
try {
await doLogout();
await logout();
} catch {
console.log('注销Token失败');
}

2
kicc-ui/src/utils/env.ts

@ -36,6 +36,7 @@ export function getAppEnvConfig() { @@ -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() { @@ -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
};
}

4
kicc-ui/types/config.d.ts vendored

@ -151,6 +151,8 @@ export interface GlobConfig { @@ -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 { @@ -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;
}

Loading…
Cancel
Save