登录流程
This commit is contained in:
parent
7ab97a1377
commit
e66a9523b2
@ -5,7 +5,7 @@ ENV = 'development'
|
||||
VITE_BASE_PATH = './'
|
||||
|
||||
# 代理配置(开发使用),必须在一行中
|
||||
VITE_APP_PROXY=[["/api","https://usp2.jsspisoft.com/api"]]
|
||||
VITE_APP_PROXY=[["/api","http://192.168.130.12:8080/api"]]
|
||||
|
||||
# 开发环境下跨域代理,请输入要跨域的api地址 - 尾部无需带'/'
|
||||
# VITE_PROXY_URL = 'http://localhost:8000'
|
||||
|
@ -19,7 +19,6 @@
|
||||
"element-plus": "2.7.4",
|
||||
"esno": "4.7.0",
|
||||
"font-awesome": "4.7.0",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash-es": "4.17.21",
|
||||
"mitt": "3.0.1",
|
||||
"nprogress": "0.2.0",
|
||||
|
@ -1,5 +1,4 @@
|
||||
import createAxios from '/@/utils/axios'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
|
||||
export function index() {
|
||||
return createAxios({
|
||||
@ -15,18 +14,17 @@ export function userinfo() {
|
||||
})
|
||||
}
|
||||
|
||||
export function login(method: 'get' | 'post', params: object = {}) {
|
||||
export function login(params: object = {}) {
|
||||
return createAxios({
|
||||
url: '/api/auth/token/invoke',
|
||||
url: '/api/auth/login',
|
||||
data: params,
|
||||
method: method,
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
// const adminInfo = useAdminInfo()
|
||||
return createAxios({
|
||||
url: '/api/auth/token/revoke',
|
||||
url: '/api/auth/logout',
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ export const changeTerminalConfigUrl = '/admin/ajax/changeTerminalConfig'
|
||||
export const clearCacheUrl = '/admin/ajax/clearCache'
|
||||
|
||||
// 公共
|
||||
export const captchaUrl = '/api/common/captcha'
|
||||
export const clickCaptchaUrl = '/api/common/clickCaptcha'
|
||||
export const captchaUrl = '/api/captchaImage'
|
||||
export const clickCaptchaUrl = '/api/captchaImage'
|
||||
export const checkClickCaptchaUrl = '/api/common/checkClickCaptcha'
|
||||
export const refreshTokenUrl = '/api/common/refreshToken'
|
||||
|
||||
@ -218,13 +218,10 @@ export function buildCaptchaUrl() {
|
||||
return getUrl() + captchaUrl + '?server=1'
|
||||
}
|
||||
|
||||
export function getCaptchaData(id: string) {
|
||||
export function getCaptchaData() {
|
||||
return createAxios({
|
||||
url: clickCaptchaUrl,
|
||||
method: 'get',
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
method: 'post',
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -87,11 +87,11 @@ const state: {
|
||||
|
||||
const load = () => {
|
||||
state.loading = true
|
||||
getCaptchaData(props.uuid).then((res) => {
|
||||
getCaptchaData().then((res) => {
|
||||
state.xy = []
|
||||
state.tip = ''
|
||||
state.loading = false
|
||||
state.captcha = res.data
|
||||
state.captcha.base64 = 'data:image\/png;base64,' + res.data.img
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
export default {
|
||||
'Please enter an account': '请输入账号',
|
||||
'Please input a password': '请输入密码',
|
||||
'Please input a captcha': '请输入验证码',
|
||||
'Hold session': '保持会话',
|
||||
'Sign in': '登录',
|
||||
}
|
||||
|
@ -160,7 +160,6 @@ const onAdminInfo = () => {
|
||||
|
||||
const onLogout = () => {
|
||||
logout().then(() => {
|
||||
debugger
|
||||
Local.remove(ADMIN_INFO)
|
||||
router.go(0)
|
||||
})
|
||||
|
@ -1407,35 +1407,35 @@ const init = () => {
|
||||
/**
|
||||
* 后台初始化请求,获取站点配置,动态路由等信息
|
||||
*/
|
||||
index().then((res) => {
|
||||
// siteConfig.dataFill(res.data.siteConfig)
|
||||
// terminal.changePort(res.data.terminal.installServicePort)
|
||||
// terminal.changePackageManager(res.data.terminal.npmPackageManager)
|
||||
// siteConfig.setInitialize(true)
|
||||
// index().then((res) => {
|
||||
// siteConfig.dataFill(res.data.siteConfig)
|
||||
// terminal.changePort(res.data.terminal.installServicePort)
|
||||
// terminal.changePackageManager(res.data.terminal.npmPackageManager)
|
||||
// siteConfig.setInitialize(true)
|
||||
|
||||
// if (!isEmpty(res.data.adminInfo)) {
|
||||
// adminInfo.dataFill(res.data.adminInfo)
|
||||
// siteConfig.setUserInitialize(true)
|
||||
// }
|
||||
// if (!isEmpty(res.data.adminInfo)) {
|
||||
// adminInfo.dataFill(res.data.adminInfo)
|
||||
// siteConfig.setUserInitialize(true)
|
||||
// }
|
||||
|
||||
if (res.data) {
|
||||
handleAdminRoute(menu)
|
||||
// if (res.data) {
|
||||
handleAdminRoute(menu)
|
||||
|
||||
// 预跳转到上次路径
|
||||
if (route.params.to) {
|
||||
const lastRoute = JSON.parse(route.params.to as string)
|
||||
if (lastRoute.path != adminBaseRoutePath) {
|
||||
let query = !isEmpty(lastRoute.query) ? lastRoute.query : {}
|
||||
routePush({ path: lastRoute.path, query: query })
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转到第一个菜单
|
||||
let firstRoute = getFirstRoute(navTabs.state.tabsViewRoutes)
|
||||
if (firstRoute) routePush(firstRoute.path)
|
||||
// 预跳转到上次路径
|
||||
if (route.params.to) {
|
||||
const lastRoute = JSON.parse(route.params.to as string)
|
||||
if (lastRoute.path != adminBaseRoutePath) {
|
||||
let query = !isEmpty(lastRoute.query) ? lastRoute.query : {}
|
||||
routePush({ path: lastRoute.path, query: query })
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 跳转到第一个菜单
|
||||
let firstRoute = getFirstRoute(navTabs.state.tabsViewRoutes)
|
||||
if (firstRoute) routePush(firstRoute.path)
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
const onAdaptiveLayout = () => {
|
||||
|
@ -90,10 +90,14 @@ function createAxios<Data = any, T = ApiPromise<Data>>(axiosConfig: AxiosRequest
|
||||
|
||||
if (config.method === 'post' && config.data) {
|
||||
// 对data进行加密
|
||||
config.data = encrypt_aes(config.data, v)
|
||||
const formData = new FormData()
|
||||
formData.append('param', encrypt_aes(config.data, v))
|
||||
config.data = formData
|
||||
} else if (config.method === 'get' && config.params) {
|
||||
// 对params进行加密
|
||||
config.params = encrypt_aes(config.params, v)
|
||||
const formData = new FormData()
|
||||
formData.append('param', encrypt_aes(config.params, v))
|
||||
config.params = formData
|
||||
}
|
||||
|
||||
// 自动携带token
|
||||
|
@ -1,35 +1,38 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
const key = ''
|
||||
const key = 'b6967ee87b86d85a'
|
||||
|
||||
export function encrypt_aes(plaintText: string, iv: string) {
|
||||
const encryptedData = CryptoJS.AES.encrypt(plaintText, key, {
|
||||
export function encrypt_aes(text: any, iv: string) {
|
||||
let plaintText = text
|
||||
if (typeof text == 'object') {
|
||||
plaintText = JSON.stringify(plaintText)
|
||||
}
|
||||
iv = CryptoJS.enc.Utf8.parse(iv)
|
||||
let pkey = CryptoJS.enc.Utf8.parse(key)
|
||||
plaintText = CryptoJS.enc.Utf8.parse(plaintText)
|
||||
const encryptedData = CryptoJS.AES.encrypt(plaintText, pkey, {
|
||||
iv,
|
||||
|
||||
mode: CryptoJS.mode.CBC,
|
||||
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
padding: CryptoJS.pad.ZeroPadding,
|
||||
})
|
||||
|
||||
// const encryptedBase64Str = encryptedData.toString()
|
||||
|
||||
// // 需要读取encryptedData上的ciphertext.toString()才能拿到跟Java一样的密文
|
||||
|
||||
// const encryptedStr = encryptedData.ciphertext.toString()
|
||||
const encryptedStr = encryptedData.ciphertext.toString(CryptoJS.enc.Base64)
|
||||
|
||||
return encryptedData.toString(CryptoJS.format.Base64)
|
||||
return encryptedStr
|
||||
}
|
||||
|
||||
export function decrypt_aes(word: string, iv: string) {
|
||||
var decrypt = CryptoJS.AES.decrypt(word, key, {
|
||||
iv = CryptoJS.enc.Utf8.parse(iv)
|
||||
let pkey = CryptoJS.enc.Utf8.parse(key)
|
||||
const decrypt = CryptoJS.AES.decrypt(word, pkey, {
|
||||
iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
padding: CryptoJS.pad.ZeroPadding,
|
||||
})
|
||||
//解密后,需要按照Utf8的方式将明文转位字符串
|
||||
var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
|
||||
|
||||
return decryptedStr
|
||||
return decrypt.toString(CryptoJS.enc.Utf8)
|
||||
}
|
||||
|
||||
export function generateRandomNumber(length: number) {
|
||||
|
@ -50,7 +50,23 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-checkbox v-model="form.keep" :label="t('login.Hold session')" size="default"></el-checkbox>
|
||||
<el-form-item v-if="state.showCaptcha" prop="captcha">
|
||||
<el-space>
|
||||
<el-input
|
||||
ref="captchaRef"
|
||||
v-model="form.code"
|
||||
type="text"
|
||||
:placeholder="t('login.Please input a captcha')"
|
||||
clearable
|
||||
>
|
||||
<template #prefix>
|
||||
<Icon name="fa fa-unlock-alt" class="form-item-icon" size="16" color="var(--el-input-icon-color)" />
|
||||
</template>
|
||||
</el-input>
|
||||
<img class="captcha-img" @click.prevent="load()" :src="state.captcha" />
|
||||
</el-space>
|
||||
</el-form-item>
|
||||
<!-- <el-checkbox v-model="form.keep" :label="t('login.Hold session')" size="default"></el-checkbox> -->
|
||||
<el-form-item>
|
||||
<el-button
|
||||
:loading="state.submitLoading"
|
||||
@ -73,6 +89,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onBeforeUnmount, reactive, ref, nextTick } from 'vue'
|
||||
import { getCaptchaData } from '/@/api/common'
|
||||
import * as pageBubble from '/@/utils/pageBubble'
|
||||
import type { FormInstance, InputInstance } from 'element-plus'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@ -80,10 +97,9 @@ import { editDefaultLang } from '/@/lang/index'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
import { login } from '/@/api/backend'
|
||||
import { uuid } from '/@/utils/random'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import router from '/@/router'
|
||||
import clickCaptcha from '/@/components/clickCaptcha'
|
||||
// import clickCaptcha from '/@/components/clickCaptcha'
|
||||
import toggleDark from '/@/utils/useDark'
|
||||
import { fullUrl } from '/@/utils/common'
|
||||
import { adminBaseRoutePath } from '/@/router/static/adminBase'
|
||||
@ -97,16 +113,18 @@ toggleDark(config.layout.isDark)
|
||||
const formRef = ref<FormInstance>()
|
||||
const usernameRef = ref<InputInstance>()
|
||||
const passwordRef = ref<InputInstance>()
|
||||
const captchaRef = ref<InputInstance>()
|
||||
const state = reactive({
|
||||
showCaptcha: false,
|
||||
showCaptcha: true,
|
||||
submitLoading: false,
|
||||
captcha: '',
|
||||
})
|
||||
const form = reactive({
|
||||
username: '',
|
||||
password: '',
|
||||
keep: false,
|
||||
captchaId: uuid(),
|
||||
captchaInfo: '',
|
||||
uuid: '',
|
||||
code: '',
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
@ -115,6 +133,7 @@ const { t } = useI18n()
|
||||
const rules = reactive({
|
||||
username: [buildValidatorData({ name: 'required', message: t('login.Please enter an account') }), buildValidatorData({ name: 'account' })],
|
||||
password: [buildValidatorData({ name: 'required', message: t('login.Please input a password') }), buildValidatorData({ name: 'password' })],
|
||||
code: [buildValidatorData({ name: 'required', message: t('login.Please input a captcha') }), buildValidatorData({ name: 'required' })],
|
||||
})
|
||||
|
||||
const focusInput = () => {
|
||||
@ -122,6 +141,8 @@ const focusInput = () => {
|
||||
usernameRef.value!.focus()
|
||||
} else if (form.password === '') {
|
||||
passwordRef.value!.focus()
|
||||
} else if (form.code === '') {
|
||||
captchaRef.value!.focus()
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +150,7 @@ onMounted(() => {
|
||||
timer = window.setTimeout(() => {
|
||||
pageBubble.init()
|
||||
}, 1000)
|
||||
|
||||
load()
|
||||
// login('get')
|
||||
// .then((res) => {
|
||||
// state.showCaptcha = res.data.captcha
|
||||
@ -148,34 +169,30 @@ onBeforeUnmount(() => {
|
||||
const onSubmitPre = () => {
|
||||
formRef.value?.validate((valid) => {
|
||||
if (valid) {
|
||||
if (state.showCaptcha) {
|
||||
clickCaptcha(form.captchaId, (captchaInfo: string) => onSubmit(captchaInfo))
|
||||
} else {
|
||||
onSubmit()
|
||||
}
|
||||
// if (state.showCaptcha) {
|
||||
// clickCaptcha(form.uuid, (captchaInfo: string) => onSubmit(captchaInfo))
|
||||
// } else {
|
||||
onSubmit()
|
||||
// }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const load = () => {
|
||||
getCaptchaData().then((res) => {
|
||||
form.uuid = res.data.uuid
|
||||
state.captcha = 'data:image\/png;base64,' + res.data.img
|
||||
})
|
||||
}
|
||||
|
||||
const onSubmit = (captchaInfo = '') => {
|
||||
state.submitLoading = true
|
||||
form.captchaInfo = captchaInfo
|
||||
let publicKey = `-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUCvEWRhSSdqchyq8bAV49Xpx8
|
||||
XYjeBzUnzTZm3FVQeFKlf3TGlNc2Uw7anVFsqU2bXBZMOhQlrFZxnLhcssD3n/LZ
|
||||
6CSptRIFg3YPi0sRwL06yov+x16DjcR4iyrQai7zzIVSS2iggy0D7bnJ5Jq8OoVs
|
||||
nbTuGGTWeRWbZ7b/yQIDAQAB
|
||||
-----END PUBLIC KEY-----`
|
||||
const encrypt = new JSEncrypt()
|
||||
encrypt.setPublicKey(publicKey)
|
||||
const encrypted = encrypt.encrypt(form.password)
|
||||
form.password = encrypted as string
|
||||
login('post', form)
|
||||
login(form)
|
||||
.then((res) => {
|
||||
adminInfo.dataFill({
|
||||
id: res.data.accountId,
|
||||
username: '',
|
||||
nickname: '',
|
||||
id: res.data.sysUser.id,
|
||||
username: res.data.sysUser.account,
|
||||
nickname: res.data.sysUser.userName,
|
||||
avatar: '',
|
||||
last_login_time: '',
|
||||
token: res.data.token,
|
||||
@ -187,6 +204,7 @@ nbTuGGTWeRWbZ7b/yQIDAQAB
|
||||
})
|
||||
.finally(() => {
|
||||
state.submitLoading = false
|
||||
load()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user