Browse Source

⚗ 重写登录逻辑,目前实现了一半

master
wangxiang 3 years ago
parent
commit
ae18d74dc1
  1. 26
      kicc-ui/src/api/sys/model/userModel.ts
  2. 2
      kicc-ui/src/api/sys/user.ts
  3. 10
      kicc-ui/src/enums/cacheEnum.ts
  4. 4
      kicc-ui/src/hooks/web/useLockPage.ts
  5. 8
      kicc-ui/src/hooks/web/usePermission.ts
  6. 2
      kicc-ui/src/router/guard/index.ts
  7. 2
      kicc-ui/src/router/guard/permissionGuard.ts
  8. 1
      kicc-ui/src/store/modules/lock.ts
  9. 10
      kicc-ui/src/store/modules/permission.ts
  10. 124
      kicc-ui/src/store/modules/user.ts
  11. 6
      kicc-ui/src/utils/auth/index.ts
  12. 15
      kicc-ui/src/utils/cache/persistent.ts
  13. 8
      kicc-ui/src/utils/cipher.ts
  14. 3
      kicc-ui/src/utils/http/axios/checkStatus.ts
  15. 12
      kicc-ui/src/utils/http/axios/index.ts
  16. 1
      kicc-ui/src/views/sys/login/LoginForm.vue
  17. 28
      kicc-ui/types/store.d.ts

26
kicc-ui/src/api/sys/model/userModel.ts

@ -49,19 +49,31 @@ export interface LoginResultModel { @@ -49,19 +49,31 @@ export interface LoginResultModel {
* @description: Get user information return value
*/
export interface GetUserInfoModel {
roles: RoleInfo[];
// 用户id
userId: string | number;
id: string;
// 用户名
username: string;
userName: string;
// 真实名字
nickName: string;
// 头像
avatar: string;
// 介绍
desc?: string;
// 角色Id
roleId: string | number;
// 所属部门ID
deptId: string;
// 所属部门名称
deptName: string;
// 邮箱
email: string;
// 菜单按钮权限
permissions: Recordable;
// 角色ID权限
roleIds: Recordable;
// 手机号
phone: string;
// 备注信息
remarks: string;
// 多租户ID
tenantId: string;
[key: string]: any;
}
export interface GetCaptchaModel {

2
kicc-ui/src/api/sys/user.ts

@ -13,7 +13,7 @@ import qs from 'qs'; @@ -13,7 +13,7 @@ import qs from 'qs';
enum Api {
Login = '/auth/oauth/token',
Logout = '/mate-uaa/auth/logout',
GetUserInfo = '/mate-uaa/auth/get/user',
GetUserInfo = '/admin/system/user/info',
GetPermCode = '/getPermCode',
GetCaptcha = '/code',
}

10
kicc-ui/src/enums/cacheEnum.ts

@ -4,18 +4,18 @@ @@ -4,18 +4,18 @@
* @author: entfrm开发团队-
* @create: 2022/4/9
*/
// 访问令牌密钥
export const ACCESS_TOKEN_KEY = 'ACCESS__TOKEN__';
// 令牌密钥
export const TOKEN_KEY = 'TOKEN__';
// 刷新令牌密钥
export const REFRESH_TOKEN_KEY = 'REFRESH__TOKEN__';
// 国际化键
export const LOCALE_KEY = 'LOCALE__';
// 用户信息键
export const USER_INFO_KEY = 'USER__INFO__';
// 角色信息键
export const ROLES_KEY = 'ROLES__KEY__';
// 项目配置键
export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__';

4
kicc-ui/src/hooks/web/useLockPage.ts

@ -26,7 +26,7 @@ export function useLockPage() { @@ -26,7 +26,7 @@ export function useLockPage() {
function resetCalcLockTimeout(): void {
// 未登录
if (!userStore.getToken) {
if (!userStore.getAccessToken) {
clear();
return;
}
@ -50,7 +50,7 @@ export function useLockPage() { @@ -50,7 +50,7 @@ export function useLockPage() {
}
watchEffect((onClean) => {
if (userStore.getToken) {
if (userStore.getAccessToken) {
resetCalcLockTimeout();
} else {
clear();

8
kicc-ui/src/hooks/web/usePermission.ts

@ -6,16 +6,18 @@ @@ -6,16 +6,18 @@
*/
import type { RouteRecordRaw } from 'vue-router';
import { usePermissionStore } from '/@/store/modules/permission';
import { usePermissionStoreWithOut } from '/@/store/modules/permission';
import { useTabs } from './useTabs';
import { router, resetRouter } from '/@/router';
import { intersection } from 'lodash-es';
import { isArray } from '/@/utils/is';
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
import { useUserStoreWithOut } from "/@/store/modules/user";
// 用户权限相关操作
export function usePermission() {
const permissionStore = usePermissionStore();
const permissionStore = usePermissionStoreWithOut();
const userStore = useUserStoreWithOut();
const { closeAll } = useTabs(router);
/**
@ -42,7 +44,7 @@ export function usePermission() { @@ -42,7 +44,7 @@ export function usePermission() {
if (!value) {
return def;
}
const allCodeList = permissionStore.getPermCodeList as string[];
const allCodeList = userStore.getPermissions as string[];
if (!isArray(value)) {
return allCodeList.includes(value);
}

2
kicc-ui/src/router/guard/index.ts

@ -55,7 +55,7 @@ function createPageLoadingGuard(router: Router) { @@ -55,7 +55,7 @@ function createPageLoadingGuard(router: Router) {
const appStore = useAppStoreWithOut();
const { getOpenPageLoading } = useTransitionSetting();
router.beforeEach(async (to) => {
if (!userStore.getToken) {
if (!userStore.getAccessToken) {
return true;
}
if (to.meta.loaded) {

2
kicc-ui/src/router/guard/permissionGuard.ts

@ -37,7 +37,7 @@ export function createPermissionGuard(router: Router) { @@ -37,7 +37,7 @@ export function createPermissionGuard(router: Router) {
return;
}
const token = userStore.getToken;
const token = userStore.getAccessToken;
// 令牌不存在
if (!token) {

1
kicc-ui/src/store/modules/lock.ts

@ -47,7 +47,6 @@ export const useLockStore = defineStore({ @@ -47,7 +47,6 @@ export const useLockStore = defineStore({
username,
password: password!,
goHome: false,
mode: 'none',
// todo: 锁屏解锁登录,需要验证码,后期完善
realKey: '',
code: '',

10
kicc-ui/src/store/modules/permission.ts

@ -20,8 +20,6 @@ import { useMessage } from '/@/hooks/web/useMessage'; @@ -20,8 +20,6 @@ import { useMessage } from '/@/hooks/web/useMessage';
import { PageEnum } from '/@/enums/pageEnum';
interface PermissionState {
// 权限代码列表
permCodeList: string[] | number[];
// 路由是否动态添加
isDynamicAddedRoute: boolean;
// 触发菜单更新
@ -33,8 +31,6 @@ interface PermissionState { @@ -33,8 +31,6 @@ interface PermissionState {
export const usePermissionStore = defineStore({
id: 'app-permission',
state: (): PermissionState => ({
// 权限代码列表
permCodeList: [],
// 路由是否动态添加
isDynamicAddedRoute: false,
// 触发菜单更新
@ -43,9 +39,6 @@ export const usePermissionStore = defineStore({ @@ -43,9 +39,6 @@ export const usePermissionStore = defineStore({
menuList: []
}),
getters: {
getPermCodeList(): string[] | number[] {
return this.permCodeList;
},
getMenuList(): Menu[] {
return this.menuList;
},
@ -57,9 +50,6 @@ export const usePermissionStore = defineStore({ @@ -57,9 +50,6 @@ export const usePermissionStore = defineStore({
},
},
actions: {
setPermCodeList(codeList: string[]) {
this.permCodeList = codeList;
},
setMenuList(list: Menu[]) {
this.menuList = list;
list?.length > 0 && this.setLastBuildMenuTime();

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

@ -5,26 +5,28 @@ @@ -5,26 +5,28 @@
* @create: 2022/4/9
*/
import type { UserInfo } from '/#/store';
import { defineStore } from 'pinia';
import { store } from '/@/store';
import { PageEnum } from '/@/enums/pageEnum';
import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum';
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { GetUserInfoModel, LoginParams } from '/@/api/sys/model/userModel';
import { doLogout, getUserInfo, loginApi } from '/@/api/sys/user';
import { useI18n } from '/@/hooks/web/useI18n';
import { useMessage } from '/@/hooks/web/useMessage';
import { router } from '/@/router';
import { usePermissionStore } from '/@/store/modules/permission';
import { RouteRecordRaw } from 'vue-router';
import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
import type {UserInfo} from '/#/store';
import {defineStore} from 'pinia';
import {store} from '/@/store';
import {PageEnum} from '/@/enums/pageEnum';
import {ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY, USER_INFO_KEY} from '/@/enums/cacheEnum';
import {getAuthCache, setAuthCache} from '/@/utils/auth';
import {GetUserInfoModel, LoginParams} from '/@/api/sys/model/userModel';
import {doLogout, getUserInfo, loginApi} from '/@/api/sys/user';
import {useI18n} from '/@/hooks/web/useI18n';
import {useMessage} from '/@/hooks/web/useMessage';
import {router} from '/@/router';
import {usePermissionStore} from '/@/store/modules/permission';
import {RouteRecordRaw} from 'vue-router';
import {PAGE_NOT_FOUND_ROUTE} from '/@/router/routes/basic';
interface UserState {
userInfo: Nullable<UserInfo>;
token?: string;
sessionTimeout?: boolean;
roleId: string | number;
sessionTimeout: boolean;
roleIds: Recordable;
permissions: Recordable;
access_token: string;
refresh_token: string;
}
export const useUserStore = defineStore({
@ -32,64 +34,84 @@ export const useUserStore = defineStore({ @@ -32,64 +34,84 @@ export const useUserStore = defineStore({
state: (): UserState => ({
// 用户信息
userInfo: null,
// token
token: undefined,
// 登录是否过期
sessionTimeout: false,
roleId: '',
// 角色ID用于权限校验
roleIds: [],
// 按钮权限标识用于权限校验
permissions: [],
// 访问令牌
access_token: '',
// 刷新令牌
refresh_token: '',
}),
getters: {
getUserInfo(): UserInfo {
return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {};
getUserInfo(): UserInfo | {[key: string]: any} {
return this.userInfo || {};
},
getToken(): string {
return this.token || getAuthCache<string>(TOKEN_KEY);
getAccessToken(): string {
return this.access_token;
},
getRefreshToken(): string {
return this.refresh_token;
},
getSessionTimeout(): boolean {
return !!this.sessionTimeout;
},
getRoleIds(): Recordable {
return this.roleIds;
},
getPermissions(): Recordable {
return this.permissions;
},
},
actions: {
setToken(info: string | undefined) {
this.token = info;
setAuthCache(TOKEN_KEY, info);
setRoleIds(roleIds: Recordable) {
this.roleIds = roleIds;
},
setRoleId(roleId: string | number) {
this.roleId = roleId;
setAuthCache(ROLES_KEY, roleId);
setPermissions(permissions: Recordable) {
this.permissions = permissions;
},
setUserInfo(info: UserInfo) {
this.userInfo = info;
setAuthCache(USER_INFO_KEY, info);
setAccessToken(accessToken: string) {
this.access_token = accessToken;
setAuthCache(ACCESS_TOKEN_KEY, accessToken);
},
setRefreshToken(refreshToken: string) {
this.refresh_token = refreshToken;
setAuthCache(REFRESH_TOKEN_KEY, refreshToken);
},
setUserInfo(userInfo: UserInfo) {
this.userInfo = userInfo;
setAuthCache(USER_INFO_KEY, userInfo);
},
setSessionTimeout(flag: boolean) {
this.sessionTimeout = flag;
},
resetState() {
this.userInfo = null;
this.token = '';
this.roleId = '';
this.sessionTimeout = false;
this.access_token = '';
this.refresh_token = '';
this.roleIds = [];
this.permissions = [];
},
/**
*
*/
/** 登录 */
async login(params: LoginParams & { goHome?: boolean; }): Promise<GetUserInfoModel | null> {
try {
debugger;
const { goHome = true, ...loginParams } = params;
const data = await loginApi(loginParams);
const { access_token } = data;
// 保存令牌
this.setToken(access_token);
const { access_token, refresh_token } = data;
this.setAccessToken(access_token);
this.setRefreshToken(refresh_token);
// 获取用户信息
const userInfo = await this.getUserInfoAction();
const sessionTimeout = this.sessionTimeout;
if (sessionTimeout) {
this.setSessionTimeout(false);
} else if (goHome) {
const permissionStore = usePermissionStore();
if (!permissionStore.isDynamicAddedRoute) {
const routes = await permissionStore.buildRoutesAction();
@ -100,6 +122,7 @@ export const useUserStore = defineStore({ @@ -100,6 +122,7 @@ export const useUserStore = defineStore({
permissionStore.setDynamicAddedRoute(true);
}
await router.replace(userInfo.homePath || PageEnum.BASE_HOME);
}
return userInfo;
} catch (error) {
@ -108,26 +131,25 @@ export const useUserStore = defineStore({ @@ -108,26 +131,25 @@ export const useUserStore = defineStore({
},
async getUserInfoAction(): Promise<UserInfo> {
const userInfo = await getUserInfo();
// 存储用户扩展信息,便于鉴权
this.setUserInfo(userInfo);
this.setRoleId(userInfo.roleId);
this.setRoleIds(userInfo.roleIds);
this.setPermissions(userInfo.permissions);
return userInfo;
},
/**
*
*/
/** 登出 */
async logout(goLogin = false) {
try {
await doLogout();
} catch {
console.log('注销Token失败');
}
this.setToken(undefined);
this.setAccessToken('');
this.setRefreshToken('');
this.setSessionTimeout(false);
goLogin && router.push(PageEnum.BASE_LOGIN);
},
/**
* 退
*/
/** 退出前确认 */
confirmLoginOut() {
const { createConfirm } = useMessage();
const { t } = useI18n();

6
kicc-ui/src/utils/auth/index.ts

@ -8,13 +8,13 @@ @@ -8,13 +8,13 @@
import { Persistent, BasicKeys } from '/@/utils/cache/persistent';
import { CacheTypeEnum } from '/@/enums/cacheEnum';
import projectSetting from '/@/settings/projectSetting';
import { TOKEN_KEY } from '/@/enums/cacheEnum';
import { ACCESS_TOKEN_KEY } from '/@/enums/cacheEnum';
const { permissionCacheType } = projectSetting;
const isLocal = permissionCacheType === CacheTypeEnum.LOCAL;
export function getToken() {
return getAuthCache(TOKEN_KEY);
export function getAccessToken() {
return getAuthCache(ACCESS_TOKEN_KEY);
}
export function getAuthCache<T>(key: BasicKeys) {

15
kicc-ui/src/utils/cache/persistent.ts vendored

@ -13,23 +13,22 @@ import type { RouteLocationNormalized } from 'vue-router'; @@ -13,23 +13,22 @@ import type { RouteLocationNormalized } from 'vue-router';
import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
import { Memory } from './memory';
import {
TOKEN_KEY,
ACCESS_TOKEN_KEY,
USER_INFO_KEY,
ROLES_KEY,
LOCK_INFO_KEY,
PROJ_CFG_KEY,
APP_LOCAL_CACHE_KEY,
APP_SESSION_CACHE_KEY,
MULTIPLE_TABS_KEY,
MULTIPLE_TABS_KEY, REFRESH_TOKEN_KEY,
} from '/@/enums/cacheEnum';
import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting';
import { toRaw } from 'vue';
import { pick, omit } from 'lodash-es';
interface BasicStore {
[TOKEN_KEY]: string | number | null | undefined;
[ACCESS_TOKEN_KEY]: string | number | null | undefined;
[REFRESH_TOKEN_KEY]: string | number | null | undefined;
[USER_INFO_KEY]: UserInfo;
[ROLES_KEY]: string[];
[LOCK_INFO_KEY]: LockInfo;
[PROJ_CFG_KEY]: ProjectConfig;
[MULTIPLE_TABS_KEY]: RouteLocationNormalized[];
@ -106,15 +105,15 @@ export class Persistent { @@ -106,15 +105,15 @@ export class Persistent {
}
window.addEventListener('beforeunload', function () {
// TOKEN_KEY 在登录或注销时已经写入到storage了,此处为了解决同时打开多个窗口时token不同步的问题
// ACCESS_TOKEN_KEY 在登录或注销时已经写入到storage了,此处为了解决同时打开多个窗口时token不同步的问题
// LOCK_INFO_KEY 在锁屏和解锁时写入,此处也不应修改
ls.set(APP_LOCAL_CACHE_KEY, {
...omit(localMemory.getCache, LOCK_INFO_KEY),
...pick(ls.get(APP_LOCAL_CACHE_KEY), [TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]),
...pick(ls.get(APP_LOCAL_CACHE_KEY), [ACCESS_TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]),
});
ss.set(APP_SESSION_CACHE_KEY, {
...omit(sessionMemory.getCache, LOCK_INFO_KEY),
...pick(ss.get(APP_SESSION_CACHE_KEY), [TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]),
...pick(ss.get(APP_SESSION_CACHE_KEY), [ACCESS_TOKEN_KEY, USER_INFO_KEY, LOCK_INFO_KEY]),
});
});

8
kicc-ui/src/utils/cipher.ts

@ -32,12 +32,12 @@ export class AesEncryption { @@ -32,12 +32,12 @@ export class AesEncryption {
};
}
encryptByAES(cipherText: string, config?: { [key: string]: any; }) {
return encrypt(cipherText, this.key, config ?? this.getOptions).toString();
encryptByAES(cipherText: string) {
return encrypt(cipherText, this.key, this.getOptions).toString();
}
decryptByAES(cipherText: string, config?: { [key: string]: any; }) {
return decrypt(cipherText, this.key, config ?? this.getOptions).toString(CryptoJS.enc.Utf8);
decryptByAES(cipherText: string) {
return decrypt(cipherText, this.key, this.getOptions).toString(CryptoJS.enc.Utf8);
}
}

3
kicc-ui/src/utils/http/axios/checkStatus.ts

@ -31,7 +31,8 @@ export function checkStatus(status: number, msg: string, errorMessageMode: Error @@ -31,7 +31,8 @@ export function checkStatus(status: number, msg: string, errorMessageMode: Error
case 401:
errMessage = t('sys.api.errMsg401');
if (stp === SessionTimeoutProcessingEnum.PAGE_COVERAGE) {
userStore.setToken(undefined);
userStore.setAccessToken('');
userStore.setRefreshToken('');
userStore.setSessionTimeout(true);
} else {
userStore.logout(true);

12
kicc-ui/src/utils/http/axios/index.ts

@ -14,7 +14,7 @@ import { useGlobSetting } from '/@/hooks/setting'; @@ -14,7 +14,7 @@ import { useGlobSetting } from '/@/hooks/setting';
import { useMessage } from '/@/hooks/web/useMessage';
import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum';
import { isString } from '/@/utils/is';
import { getToken } from '/@/utils/auth';
import { getAccessToken } from '/@/utils/auth';
import { setObjToUrlParams, deepMerge } from '/@/utils';
import { useI18n } from '/@/hooks/web/useI18n';
import { joinTimestamp, formatRequestDate } from './helper';
@ -105,15 +105,15 @@ const transform: AxiosTransform = { @@ -105,15 +105,15 @@ const transform: AxiosTransform = {
*/
requestInterceptors: (config, options) => {
// 请求之前处理config
const token = getToken();
const token = getAccessToken();
const { clientId, clientSecret } = globSetting;
// 是否使用JWT
// 使用token进行请求
if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
(config as Recordable).headers.Authorization = options.authenticationScheme
? `${options.authenticationScheme} ${token}`
: token;
} else {
// 添加客户端信息
// 使用客户端信息密钥请求
(config as Recordable).headers.Authorization = `Basic ${Base64.encode(`${clientId}:${clientSecret}`)}`;
}
return config;
@ -167,9 +167,9 @@ const transform: AxiosTransform = { @@ -167,9 +167,9 @@ const transform: AxiosTransform = {
function createAxios(opt?: Partial<CreateAxiosOptions>) {
return new VAxios(
deepMerge({
// JWT认证方案,例如:Bearer
// 认证方案,例如:Bearer
// 其他方案: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
authenticationScheme: '',
authenticationScheme: 'Bearer',
timeout: 10 * 1000,
// 接口可能会有通用的地址部分,可以统一抽取出来
urlPrefix: urlPrefix,

1
kicc-ui/src/views/sys/login/LoginForm.vue

@ -142,7 +142,6 @@ @@ -142,7 +142,6 @@
}
async function handleLogin() {
debugger
const data = await validForm();
if (!data) return;
try {

28
kicc-ui/types/store.d.ts vendored

@ -17,21 +17,33 @@ export interface LockInfo { @@ -17,21 +17,33 @@ export interface LockInfo {
}
export interface UserInfo {
roles: RoleInfo[];
// 用户id
userId: string | number;
id: string;
// 用户名
username: string;
userName: string;
// 真实名字
nickName: string;
// 头像
avatar: string;
// 介绍
desc?: string;
// 所属部门ID
deptId: string;
// 所属部门名称
deptName: string;
// 邮箱
email: string;
// 菜单按钮权限
permissions: Recordable;
// 角色ID权限
roleIds: Recordable;
// 手机号
phone: string;
// 备注信息
remarks: string;
// 多租户ID
tenantId: string;
// 指定登录后首页跳转
homePath?: string;
// 角色Id
roleId: string | number;
[key: string]: any;
}
export interface BeforeMiniState {

Loading…
Cancel
Save