Commit 818e7020 authored by guxukai's avatar guxukai

chore: token登录

parent e8cb3bc2
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
"@vuelidate/validators": "^2.0.0-alpha.25", "@vuelidate/validators": "^2.0.0-alpha.25",
"axios": "0.21.1", "axios": "0.21.1",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"crypto-js": "^4.1.1",
"element-plus": "^1.2.0-beta.6", "element-plus": "^1.2.0-beta.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"miragejs": "^0.1.43", "miragejs": "^0.1.43",
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
"@tailwindcss/forms": "^0.4.0", "@tailwindcss/forms": "^0.4.0",
"@tailwindcss/line-clamp": "^0.3.0", "@tailwindcss/line-clamp": "^0.3.0",
"@tailwindcss/typography": "^0.5.0", "@tailwindcss/typography": "^0.5.0",
"@types/crypto-js": "^4.0.2",
"@types/lodash": "^4.14.178", "@types/lodash": "^4.14.178",
"@typescript-eslint/eslint-plugin": "^4.18.0", "@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0", "@typescript-eslint/parser": "^4.18.0",
......
...@@ -4,6 +4,7 @@ import { merge } from 'lodash' ...@@ -4,6 +4,7 @@ import { merge } from 'lodash'
import { addPendingRequest, removePendingRequest } from '@shared/http/utils' import { addPendingRequest, removePendingRequest } from '@shared/http/utils'
import { MessageUtils } from '@shared/utils/message-utils' import { MessageUtils } from '@shared/utils/message-utils'
import { HttpResponse } from '@shared/http/HttpResponse' import { HttpResponse } from '@shared/http/HttpResponse'
import { authStore } from '@shared/store/modules/auth'
// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1 // 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = { const defaultConfig: AxiosRequestConfig = {
...@@ -31,6 +32,10 @@ class PureHttp { ...@@ -31,6 +32,10 @@ class PureHttp {
private httpInterceptorsRequest(): void { private httpInterceptorsRequest(): void {
this.axiosInstance.interceptors.request.use( this.axiosInstance.interceptors.request.use(
(config: PureHttpRequestConfig) => { (config: PureHttpRequestConfig) => {
const token = authStore.loginInfo?.token
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
const $config = config const $config = config
// 优先判断post/get等方法是否传入回调,否则执行初始化设置等回掉 // 优先判断post/get等方法是否传入回调,否则执行初始化设置等回掉
if (typeof config.beforeRequestCallback === 'function') { if (typeof config.beforeRequestCallback === 'function') {
...@@ -86,48 +91,7 @@ class PureHttp { ...@@ -86,48 +91,7 @@ class PureHttp {
MessageUtils.warning(message) MessageUtils.warning(message)
return Promise.reject(error) return Promise.reject(error)
} }
switch (error.response?.status) { return Promise.resolve(error.response?.data)
case 403:
message = '拒绝访问(403)'
MessageUtils.warning(message)
break
case 404:
message = '资源不存在(404)'
MessageUtils.warning(message)
break
case 408:
message = '请求超时(404)'
MessageUtils.warning(message)
break
case 500:
message = '服务器错误(500)'
MessageUtils.warning(message)
break
case 501:
message = '服务未实现(501)'
MessageUtils.warning(message)
break
case 502:
message = '网络错误(502)'
MessageUtils.warning(message)
break
case 503:
message = '服务不可用(503)'
MessageUtils.warning(message)
break
case 504:
message = '网络超时(504)'
MessageUtils.warning(message)
break
case 505:
message = 'HTTP版本不受支持(505)'
MessageUtils.warning(message)
break
default:
MessageUtils.warning(message)
break
}
return Promise.reject(error)
}, },
) )
} }
......
...@@ -107,6 +107,12 @@ import { ref, toRaw, onMounted, getCurrentInstance } from 'vue' ...@@ -107,6 +107,12 @@ import { ref, toRaw, onMounted, getCurrentInstance } from 'vue'
import { ArrowRight } from '@element-plus/icons-vue' import { ArrowRight } from '@element-plus/icons-vue'
import AsideMenuList from '@shared/layouts/components/aside-menu-list/index.vue' import AsideMenuList from '@shared/layouts/components/aside-menu-list/index.vue'
import { layoutStore } from '@shared/store/modules/layout' import { layoutStore } from '@shared/store/modules/layout'
import { useRequest } from 'vue-request'
import { AuthLicenseStatus } from '../models/gateway/AuthLicenseStatus'
import { AuthLogout } from '../models/gateway/AuthLogout'
import { GATEWAY_CODE } from '../http/constants'
import { authStore } from '../store/modules/auth'
import { MessageUtils } from '../utils/message-utils'
const PROJECT_NAME = process.env.PROJECT_NAME const PROJECT_NAME = process.env.PROJECT_NAME
let { proxy } = getCurrentInstance() let { proxy } = getCurrentInstance()
...@@ -202,7 +208,20 @@ const fullScreen = function () { ...@@ -202,7 +208,20 @@ const fullScreen = function () {
} }
isFullScreen.value = !isFullScreen.value isFullScreen.value = !isFullScreen.value
} }
const {
data: logoutData,
loading: logoutLoading,
error: logoutError,
run: logoutRun,
} = useRequest(() => AuthLogout.delete(), { manual: true })
const handleLogout = () => { const handleLogout = () => {
proxy.$router.replace('/login') logoutRun().then(res => {
if (res?.code === GATEWAY_CODE.success) {
authStore.$reset()
proxy.$router.replace({ name: 'login' })
} else {
MessageUtils.warning(res?.message)
}
})
} }
</script> </script>
...@@ -2,6 +2,7 @@ import { deserialize, JsonProperty, Serializable } from 'typescript-json-seriali ...@@ -2,6 +2,7 @@ import { deserialize, JsonProperty, Serializable } from 'typescript-json-seriali
import { Model } from '@shared/models/Model' import { Model } from '@shared/models/Model'
import { api } from '@shared/http/axios' import { api } from '@shared/http/axios'
import { HttpResponse } from '@shared/http/HttpResponse' import { HttpResponse } from '@shared/http/HttpResponse'
import { Encrypt } from '@shared/utils/secret-utils'
@Serializable() @Serializable()
export class AuthLoginPostReq extends Model<AuthLoginPostReq> { export class AuthLoginPostReq extends Model<AuthLoginPostReq> {
@JsonProperty() username: string @JsonProperty() username: string
...@@ -21,8 +22,11 @@ export class AuthLogin extends Model<AuthLogin> { ...@@ -21,8 +22,11 @@ export class AuthLogin extends Model<AuthLogin> {
super(payload) super(payload)
} }
static async post(payload: AuthLoginPostReq) { static async post(payload: AuthLoginPostReq) {
return await api.post<HttpResponse>('/auth/login', { return await api.post<HttpResponse<AuthLogin>>('/auth/login', {
data: payload, data: {
...payload,
password: Encrypt(payload.password),
},
}) })
} }
} }
import { Serializable } from 'typescript-json-serializer' import { JsonProperty, Serializable } from 'typescript-json-serializer'
import { Model } from '@shared/models/Model' import { Model } from '@shared/models/Model'
import { api } from '@shared/http/axios' import { api } from '@shared/http/axios'
import { Encrypt } from '@shared/utils/secret-utils'
@Serializable() @Serializable()
export class UserRegisterPostReq extends Model<UserRegisterPostReq> { export class UserRegisterPostReq extends Model<UserRegisterPostReq> {
uname: string @JsonProperty() uname: string
mail: string @JsonProperty() mail: string
phoneNum: string @JsonProperty() phoneNum: string
password: string @JsonProperty() password: string
verificode: string @JsonProperty() verificode: string
} }
@Serializable() @Serializable()
export class UserRegister { export class UserRegister {
static async post(payload: UserRegisterPostReq) { static async post(payload: UserRegisterPostReq) {
return await api.post('/services/user-service/user/register', { return await api.post('/services/user-service/user/register', {
data: payload, data: {
...payload,
password: Encrypt(payload.password),
},
}) })
} }
} }
...@@ -64,6 +64,7 @@ import { MessageUtils } from '@shared/utils/message-utils' ...@@ -64,6 +64,7 @@ import { MessageUtils } from '@shared/utils/message-utils'
import { GATEWAY_CODE } from '@shared/http/constants' import { GATEWAY_CODE } from '@shared/http/constants'
import { AuthRegisterStatus } from '@shared/models/gateway/AuthRegisterStatus' import { AuthRegisterStatus } from '@shared/models/gateway/AuthRegisterStatus'
import { AuthLicenseStatus } from '@shared/models/gateway/AuthLicenseStatus' import { AuthLicenseStatus } from '@shared/models/gateway/AuthLicenseStatus'
import { authStore } from '@shared/store/modules/auth'
const $router = useRouter() const $router = useRouter()
const captchaUrl = ref(`${process.env.API_PREFIX}/api/kaptcha/kaptcha`) const captchaUrl = ref(`${process.env.API_PREFIX}/api/kaptcha/kaptcha`)
const authLoginForm = reactive(new AuthLoginPostReq({})) const authLoginForm = reactive(new AuthLoginPostReq({}))
...@@ -98,6 +99,9 @@ const handleSubmitForm = async () => { ...@@ -98,6 +99,9 @@ const handleSubmitForm = async () => {
if (res?.code === GATEWAY_CODE.success) { if (res?.code === GATEWAY_CODE.success) {
loginRun().then(async res => { loginRun().then(async res => {
if (res?.data) { if (res?.data) {
authStore.$patch({
loginInfo: res.data,
})
await $router.push('/') await $router.push('/')
} else { } else {
MessageUtils.warning(res?.message) MessageUtils.warning(res?.message)
......
...@@ -2,9 +2,9 @@ import { formatRoute } from './utils' ...@@ -2,9 +2,9 @@ import { formatRoute } from './utils'
//引入配置文件router.json //引入配置文件router.json
const routerMenu = require(`@${process.env.NAME}/json/routes.json`).children const routerMenu = require(`@${process.env.NAME}/json/routes.json`).children
//初始化 //初始化
export const CONFIG_ROUTES = formatRoute(routerMenu) export const CROPPED_ROUTES = formatRoute(routerMenu)
export const STATIC_ROUTES = [ export const FIXED_ROUTES = [
{ {
path: '/login', path: '/login',
name: 'login', name: 'login',
...@@ -20,6 +20,8 @@ export const STATIC_ROUTES = [ ...@@ -20,6 +20,8 @@ export const STATIC_ROUTES = [
name: 'register', name: 'register',
component: () => import('@shared/pages/fixed/register/index.vue'), component: () => import('@shared/pages/fixed/register/index.vue'),
}, },
]
export const SYSTEM_ROUTES = [
{ {
path: '/401', path: '/401',
name: '401', name: '401',
......
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import { CONFIG_ROUTES, LOOKUP_ROUTES, STATIC_ROUTES } from './constants' import { CROPPED_ROUTES, LOOKUP_ROUTES, FIXED_ROUTES, SYSTEM_ROUTES } from './constants'
import { zookeeper } from './zookeeper' import { zookeeper } from './zookeeper'
const routes = [ const routes = [
...@@ -7,9 +7,10 @@ const routes = [ ...@@ -7,9 +7,10 @@ const routes = [
path: '/', path: '/',
name: 'default', name: 'default',
component: () => import('@shared/layouts/default-layout.vue'), component: () => import('@shared/layouts/default-layout.vue'),
children: [...CONFIG_ROUTES, ...LOOKUP_ROUTES], children: [...CROPPED_ROUTES, ...LOOKUP_ROUTES],
}, },
...STATIC_ROUTES, ...FIXED_ROUTES,
...SYSTEM_ROUTES,
] ]
export const router = createRouter({ export const router = createRouter({
history: createWebHistory(process.env.PUBLIC_URL), history: createWebHistory(process.env.PUBLIC_URL),
......
import { Router } from 'vue-router' import { Router } from 'vue-router'
import { pendingRequest } from '@shared/http/utils' import { pendingRequest } from '@shared/http/utils'
import { FIXED_ROUTES } from '@shared/router/constants'
import { authStore } from '@shared/store/modules/auth'
// 路由白名单
const whiteList = FIXED_ROUTES.map(_ => _.name)
export const zookeeper = (router: Router): void => { export const zookeeper = (router: Router): void => {
// 添加异常处理 // 添加异常处理
const originalPush = router.push const originalPush = router.push
...@@ -19,4 +22,23 @@ export const zookeeper = (router: Router): void => { ...@@ -19,4 +22,23 @@ export const zookeeper = (router: Router): void => {
}) })
pendingRequest.clear() pendingRequest.clear()
}) })
router.beforeEach(async (to, from, next) => {
const isInWhiteList = whiteList.indexOf(to.name as string) !== -1
// 判断用户是否已经登录
if (authStore.loginInfo?.token) {
// 已登录
if (isInWhiteList) {
next({ name: 'home' })
} else {
next()
}
} else {
if (isInWhiteList) {
next()
} else {
// 未登录
next({ name: 'login' })
}
}
})
} }
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { store } from '@shared/store' import { store } from '@shared/store'
import { AuthType } from '@shared/types/auth' import { AuthType } from '@shared/types/auth'
import { AuthLogin } from '@shared/models/gateway/AuthLogin'
export const authStore = defineStore('auth', { export const authStore = defineStore('auth', {
state: (): AuthType => ({}), state: (): AuthType => ({
loginInfo: new AuthLogin({}),
}),
actions: {}, actions: {},
persist: { persist: {
key: 'layout', key: 'auth',
storage: window.sessionStorage, storage: window.sessionStorage,
paths: [], paths: ['loginInfo'],
overwrite: true, overwrite: true,
}, },
})(store) })(store)
export type AuthType = {} import { AuthLogin } from '@shared/models/gateway/AuthLogin'
export type AuthType = {
loginInfo: AuthLogin
}
import CryptoJS from 'crypto-js'
const key = CryptoJS.enc.Utf8.parse('1234123412ABCDEF') // 十六位十六进制数作为密钥
const iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412') // 十六位十六进制数作为密钥偏移量
// 解密方法
export function Decrypt(word) {
const encryptedHexStr = CryptoJS.enc.Hex.parse(word)
const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr)
const decrypt = CryptoJS.AES.decrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
})
const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
return decryptedStr.toString()
}
// 加密方法
export function Encrypt(word) {
const srcs = CryptoJS.enc.Utf8.parse(word)
const encrypted = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
})
return encrypted.ciphertext.toString().toUpperCase()
}
...@@ -1319,6 +1319,11 @@ ...@@ -1319,6 +1319,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/crypto-js@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.0.2.tgz#4524325a175bf819fec6e42560c389ce1fb92c97"
integrity sha512-sCVniU+h3GcGqxOmng11BRvf9TfN9yIs8KKjB8C8d75W69cpTfZG80gau9yTx5SxF3gvHGbJhdESzzvnjtf3Og==
"@types/cssnano@^4.0.1": "@types/cssnano@^4.0.1":
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/cssnano/-/cssnano-4.0.1.tgz#67fa912753d80973a016e7684a47fedf338aacff" resolved "https://registry.yarnpkg.com/@types/cssnano/-/cssnano-4.0.1.tgz#67fa912753d80973a016e7684a47fedf338aacff"
...@@ -3511,6 +3516,11 @@ crypto-browserify@^3.12.0: ...@@ -3511,6 +3516,11 @@ crypto-browserify@^3.12.0:
randombytes "^2.0.0" randombytes "^2.0.0"
randomfill "^1.0.3" randomfill "^1.0.3"
crypto-js@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf"
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
css-blank-pseudo@^2.0.0: css-blank-pseudo@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-2.0.0.tgz#10667f9c5f91e4fbde76c4efac55e8eaa6ed9967" resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-2.0.0.tgz#10667f9c5f91e4fbde76c4efac55e8eaa6ed9967"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment