mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-07 17:10:07 +08:00
feat: mfa 登录实现
This commit is contained in:
parent
389e268407
commit
9f5e9d26f5
@ -37,6 +37,25 @@ func (b *BaseApi) Login(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, user)
|
helper.SuccessWithData(c, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) MFALogin(c *gin.Context) {
|
||||||
|
var req dto.MFALogin
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := global.VALID.Struct(req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := authService.MFALogin(c, req)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, user)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *BaseApi) LogOut(c *gin.Context) {
|
func (b *BaseApi) LogOut(c *gin.Context) {
|
||||||
if err := authService.LogOut(c); err != nil {
|
if err := authService.LogOut(c); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
@ -34,3 +34,11 @@ type Login struct {
|
|||||||
CaptchaID string `json:"captchaID"`
|
CaptchaID string `json:"captchaID"`
|
||||||
AuthMethod string `json:"authMethod"`
|
AuthMethod string `json:"authMethod"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MFALogin struct {
|
||||||
|
Name string `json:"name" validate:"name,required"`
|
||||||
|
Password string `json:"password" validate:"required"`
|
||||||
|
Secret string `json:"secret" validate:"required"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
AuthMethod string `json:"authMethod"`
|
||||||
|
}
|
||||||
|
@ -6,8 +6,10 @@ type CaptchaResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserLoginInfo struct {
|
type UserLoginInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
MfaStatus string `json:"mfaStatus"`
|
||||||
|
MfaSecret string `json:"mfaSecret"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MfaCredential struct {
|
type MfaCredential struct {
|
||||||
|
@ -39,9 +39,45 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if info.Password != pass {
|
if info.Password != pass && nameSetting.Value == info.Name {
|
||||||
return nil, errors.New("login failed")
|
return nil, errors.New("login failed")
|
||||||
}
|
}
|
||||||
|
mfa, err := settingRepo.Get(settingRepo.WithByKey("MFAStatus"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if mfa.Value == "enable" {
|
||||||
|
mfaSecret, err := settingRepo.Get(settingRepo.WithByKey("MFASecret"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &dto.UserLoginInfo{Name: nameSetting.Value, MfaStatus: mfa.Value, MfaSecret: mfaSecret.Value}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.generateSession(c, info.Name, info.AuthMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *AuthService) MFALogin(c *gin.Context, info dto.MFALogin) (*dto.UserLoginInfo, error) {
|
||||||
|
nameSetting, err := settingRepo.Get(settingRepo.WithByKey("UserName"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||||
|
}
|
||||||
|
passwrodSetting, err := settingRepo.Get(settingRepo.WithByKey("Password"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithMessage(constant.ErrRecordNotFound, err.Error())
|
||||||
|
}
|
||||||
|
pass, err := encrypt.StringDecrypt(passwrodSetting.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if info.Password != pass && nameSetting.Value == info.Name {
|
||||||
|
return nil, errors.New("login failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.generateSession(c, info.Name, info.AuthMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *AuthService) generateSession(c *gin.Context, name, authMethod string) (*dto.UserLoginInfo, error) {
|
||||||
setting, err := settingRepo.Get(settingRepo.WithByKey("SessionTimeout"))
|
setting, err := settingRepo.Get(settingRepo.WithByKey("SessionTimeout"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -51,16 +87,16 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.AuthMethod == constant.AuthMethodJWT {
|
if authMethod == constant.AuthMethodJWT {
|
||||||
j := jwt.NewJWT()
|
j := jwt.NewJWT()
|
||||||
claims := j.CreateClaims(jwt.BaseClaims{
|
claims := j.CreateClaims(jwt.BaseClaims{
|
||||||
Name: nameSetting.Value,
|
Name: name,
|
||||||
}, lifeTime)
|
}, lifeTime)
|
||||||
token, err := j.CreateToken(claims)
|
token, err := j.CreateToken(claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &dto.UserLoginInfo{Name: nameSetting.Value, Token: token}, err
|
return &dto.UserLoginInfo{Name: name, Token: token}, nil
|
||||||
}
|
}
|
||||||
sID, _ := c.Cookie(constant.SessionName)
|
sID, _ := c.Cookie(constant.SessionName)
|
||||||
sessionUser, err := global.SESSION.Get(sID)
|
sessionUser, err := global.SESSION.Get(sID)
|
||||||
@ -71,13 +107,13 @@ func (u *AuthService) Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &dto.UserLoginInfo{Name: nameSetting.Value}, nil
|
return &dto.UserLoginInfo{Name: name}, nil
|
||||||
}
|
}
|
||||||
if err := global.SESSION.Set(sID, sessionUser, lifeTime); err != nil {
|
if err := global.SESSION.Set(sID, sessionUser, lifeTime); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &dto.UserLoginInfo{Name: nameSetting.Value}, nil
|
return &dto.UserLoginInfo{Name: name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *AuthService) LogOut(c *gin.Context) error {
|
func (u *AuthService) LogOut(c *gin.Context) error {
|
||||||
|
@ -14,6 +14,7 @@ func (s *BaseRouter) InitBaseRouter(Router *gin.RouterGroup) {
|
|||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
baseRouter.GET("captcha", baseApi.Captcha)
|
baseRouter.GET("captcha", baseApi.Captcha)
|
||||||
|
baseRouter.POST("mfalogin", baseApi.MFALogin)
|
||||||
withRecordRouter.POST("login", baseApi.Login)
|
withRecordRouter.POST("login", baseApi.Login)
|
||||||
withRecordRouter.POST("logout", baseApi.LogOut)
|
withRecordRouter.POST("logout", baseApi.LogOut)
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,18 @@ export namespace Login {
|
|||||||
captchaID: string;
|
captchaID: string;
|
||||||
authMethod: string;
|
authMethod: string;
|
||||||
}
|
}
|
||||||
|
export interface MFALoginForm {
|
||||||
|
name: string;
|
||||||
|
password: string;
|
||||||
|
secret: string;
|
||||||
|
code: string;
|
||||||
|
authMethod: string;
|
||||||
|
}
|
||||||
export interface ResLogin {
|
export interface ResLogin {
|
||||||
name: string;
|
name: string;
|
||||||
token: string;
|
token: string;
|
||||||
|
mfaStatus: string;
|
||||||
|
mfaSecret: string;
|
||||||
}
|
}
|
||||||
export interface ResCaptcha {
|
export interface ResCaptcha {
|
||||||
imagePath: string;
|
imagePath: string;
|
||||||
|
@ -5,6 +5,10 @@ export const loginApi = (params: Login.ReqLoginForm) => {
|
|||||||
return http.post<Login.ResLogin>(`/auth/login`, params);
|
return http.post<Login.ResLogin>(`/auth/login`, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mfaLoginApi = (params: Login.MFALoginForm) => {
|
||||||
|
return http.post<Login.ResLogin>(`/auth/mfalogin`, params);
|
||||||
|
};
|
||||||
|
|
||||||
export const getCaptcha = () => {
|
export const getCaptcha = () => {
|
||||||
return http.get<Login.ResCaptcha>(`/auth/captcha`);
|
return http.get<Login.ResCaptcha>(`/auth/captcha`);
|
||||||
};
|
};
|
||||||
|
@ -60,6 +60,7 @@ export default {
|
|||||||
'Run the following command on the SSH terminal to solve the problem: 1. View the /etc/init.d/bt default command on the panel',
|
'Run the following command on the SSH terminal to solve the problem: 1. View the /etc/init.d/bt default command on the panel',
|
||||||
warnning:
|
warnning:
|
||||||
'Note: [Closing the security entrance] will make your panel login address directly exposed to the Internet, very dangerous, please exercise caution',
|
'Note: [Closing the security entrance] will make your panel login address directly exposed to the Internet, very dangerous, please exercise caution',
|
||||||
|
codeInput: 'Please enter the 6-digit verification code of the MFA validator',
|
||||||
},
|
},
|
||||||
rule: {
|
rule: {
|
||||||
username: 'Please enter a username',
|
username: 'Please enter a username',
|
||||||
|
@ -68,6 +68,7 @@ export default {
|
|||||||
solution: '解决方法:',
|
solution: '解决方法:',
|
||||||
solutionHelper: '在SSH终端输入以下一种命令来解决 1.查看面板入口:/etc/init.d/bt default',
|
solutionHelper: '在SSH终端输入以下一种命令来解决 1.查看面板入口:/etc/init.d/bt default',
|
||||||
warnning: '注意:【关闭安全入口】将使您的面板登录地址被直接暴露在互联网上,非常危险,请谨慎操作',
|
warnning: '注意:【关闭安全入口】将使您的面板登录地址被直接暴露在互联网上,非常危险,请谨慎操作',
|
||||||
|
codeInput: '请输入MFA验证器的 6 位验证码',
|
||||||
},
|
},
|
||||||
rule: {
|
rule: {
|
||||||
username: '请输入用户名',
|
username: '请输入用户名',
|
||||||
|
@ -1,42 +1,75 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" size="large">
|
<div>
|
||||||
<el-form-item prop="username">
|
<div v-if="mfaShow" class="login-mfa-form">
|
||||||
<el-input v-model="loginForm.name">
|
<div class="info-text">
|
||||||
<template #prefix>
|
<span style="font-size: 14px">{{ $t('commons.login.codeInput') }}</span>
|
||||||
<el-icon class="el-input__icon">
|
</div>
|
||||||
<user />
|
<div>
|
||||||
</el-icon>
|
<span>Secret:{{ mfaLoginForm.secret }}</span>
|
||||||
</template>
|
</div>
|
||||||
</el-input>
|
<el-input v-model="mfaLoginForm.code"></el-input>
|
||||||
</el-form-item>
|
<el-button class="login-btn" type="primary" @click="mfaLogin()">
|
||||||
<el-form-item prop="password">
|
{{ $t('commons.button.login') }}
|
||||||
<el-input type="password" v-model="loginForm.password" show-password autocomplete="new-password">
|
</el-button>
|
||||||
<template #prefix>
|
</div>
|
||||||
<el-icon class="el-input__icon">
|
<div v-if="!mfaShow">
|
||||||
<lock />
|
<div class="login-form">
|
||||||
</el-icon>
|
<div class="login-logo">
|
||||||
</template>
|
<img class="login-icon" src="@/assets/images/logo.svg" alt="" />
|
||||||
</el-input>
|
<h2 class="logo-text">1Panel</h2>
|
||||||
</el-form-item>
|
</div>
|
||||||
</el-form>
|
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" size="large">
|
||||||
<el-form-item prop="captcha">
|
<el-form-item prop="username">
|
||||||
<div class="vPicBox">
|
<el-input v-model="loginForm.name">
|
||||||
<el-input v-model="loginForm.captcha" :placeholder="$t('commons.login.captchaHelper')" style="width: 60%" />
|
<template #prefix>
|
||||||
<div class="vPic">
|
<el-icon class="el-input__icon">
|
||||||
<img
|
<user />
|
||||||
v-if="captcha.imagePath"
|
</el-icon>
|
||||||
:src="captcha.imagePath"
|
</template>
|
||||||
:alt="$t('commons.login.captchaHelper')"
|
</el-input>
|
||||||
@click="loginVerify()"
|
</el-form-item>
|
||||||
/>
|
<el-form-item prop="password">
|
||||||
|
<el-input
|
||||||
|
type="password"
|
||||||
|
v-model="loginForm.password"
|
||||||
|
show-password
|
||||||
|
autocomplete="new-password"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon class="el-input__icon">
|
||||||
|
<lock />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form-item prop="captcha">
|
||||||
|
<div class="vPicBox">
|
||||||
|
<el-input
|
||||||
|
v-model="loginForm.captcha"
|
||||||
|
:placeholder="$t('commons.login.captchaHelper')"
|
||||||
|
style="width: 60%"
|
||||||
|
/>
|
||||||
|
<div class="vPic">
|
||||||
|
<img
|
||||||
|
v-if="captcha.imagePath"
|
||||||
|
:src="captcha.imagePath"
|
||||||
|
:alt="$t('commons.login.captchaHelper')"
|
||||||
|
@click="loginVerify()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="login-btn">
|
||||||
|
<el-button round @click="resetForm(loginFormRef)" size="large">
|
||||||
|
{{ $t('commons.button.reset') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button round @click="login(loginFormRef)" size="large" type="primary" :loading="loading">
|
||||||
|
{{ $t('commons.button.login') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
|
||||||
<div class="login-btn">
|
|
||||||
<el-button round @click="resetForm(loginFormRef)" size="large">{{ $t('commons.button.reset') }}</el-button>
|
|
||||||
<el-button round @click="login(loginFormRef)" size="large" type="primary" :loading="loading">
|
|
||||||
{{ $t('commons.button.login') }}
|
|
||||||
</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -46,7 +79,7 @@ import { useRouter } from 'vue-router';
|
|||||||
import { Login } from '@/api/interface';
|
import { Login } from '@/api/interface';
|
||||||
import type { ElForm } from 'element-plus';
|
import type { ElForm } from 'element-plus';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { loginApi, getCaptcha } from '@/api/modules/auth';
|
import { loginApi, getCaptcha, mfaLoginApi } from '@/api/modules/auth';
|
||||||
import { GlobalStore } from '@/store';
|
import { GlobalStore } from '@/store';
|
||||||
import { MenuStore } from '@/store/modules/menu';
|
import { MenuStore } from '@/store/modules/menu';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
@ -54,7 +87,6 @@ import i18n from '@/lang';
|
|||||||
const globalStore = GlobalStore();
|
const globalStore = GlobalStore();
|
||||||
const menuStore = MenuStore();
|
const menuStore = MenuStore();
|
||||||
|
|
||||||
// 定义 formRef(校验规则)
|
|
||||||
type FormInstance = InstanceType<typeof ElForm>;
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
const loginFormRef = ref<FormInstance>();
|
const loginFormRef = ref<FormInstance>();
|
||||||
const loginRules = reactive({
|
const loginRules = reactive({
|
||||||
@ -62,7 +94,6 @@ const loginRules = reactive({
|
|||||||
password: [{ required: true, message: i18n.global.t('commons.rule.password'), trigger: 'blur' }],
|
password: [{ required: true, message: i18n.global.t('commons.rule.password'), trigger: 'blur' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 登录表单数据
|
|
||||||
const loginForm = reactive<Login.ReqLoginForm>({
|
const loginForm = reactive<Login.ReqLoginForm>({
|
||||||
name: 'admin',
|
name: 'admin',
|
||||||
password: 'Calong@2015',
|
password: 'Calong@2015',
|
||||||
@ -70,6 +101,13 @@ const loginForm = reactive<Login.ReqLoginForm>({
|
|||||||
captchaID: '',
|
captchaID: '',
|
||||||
authMethod: '',
|
authMethod: '',
|
||||||
});
|
});
|
||||||
|
const mfaLoginForm = reactive<Login.MFALoginForm>({
|
||||||
|
name: 'admin',
|
||||||
|
password: 'Calong@2015',
|
||||||
|
secret: '',
|
||||||
|
code: '',
|
||||||
|
authMethod: '',
|
||||||
|
});
|
||||||
|
|
||||||
const captcha = reactive<Login.ResCaptcha>({
|
const captcha = reactive<Login.ResCaptcha>({
|
||||||
captchaID: '',
|
captchaID: '',
|
||||||
@ -78,6 +116,8 @@ const captcha = reactive<Login.ResCaptcha>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
|
const mfaShow = ref<boolean>(false);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const login = (formEl: FormInstance | undefined) => {
|
const login = (formEl: FormInstance | undefined) => {
|
||||||
@ -93,7 +133,12 @@ const login = (formEl: FormInstance | undefined) => {
|
|||||||
captchaID: captcha.captchaID,
|
captchaID: captcha.captchaID,
|
||||||
authMethod: '',
|
authMethod: '',
|
||||||
};
|
};
|
||||||
await loginApi(requestLoginForm);
|
const res = await loginApi(requestLoginForm);
|
||||||
|
if (res.data.mfaStatus === 'enable') {
|
||||||
|
mfaShow.value = true;
|
||||||
|
mfaLoginForm.secret = res.data.mfaSecret;
|
||||||
|
return;
|
||||||
|
}
|
||||||
globalStore.setLogStatus(true);
|
globalStore.setLogStatus(true);
|
||||||
menuStore.setMenuList([]);
|
menuStore.setMenuList([]);
|
||||||
ElMessage.success(i18n.global.t('commons.msg.loginSuccess'));
|
ElMessage.success(i18n.global.t('commons.msg.loginSuccess'));
|
||||||
@ -106,6 +151,18 @@ const login = (formEl: FormInstance | undefined) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mfaLogin = async () => {
|
||||||
|
if (mfaLoginForm.code) {
|
||||||
|
mfaLoginForm.name = loginForm.name;
|
||||||
|
mfaLoginForm.password = loginForm.password;
|
||||||
|
await mfaLoginApi(mfaLoginForm);
|
||||||
|
globalStore.setLogStatus(true);
|
||||||
|
menuStore.setMenuList([]);
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.loginSuccess'));
|
||||||
|
router.push({ name: 'home' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const resetForm = (formEl: FormInstance | undefined) => {
|
const resetForm = (formEl: FormInstance | undefined) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
formEl.resetFields();
|
formEl.resetFields();
|
||||||
|
@ -67,5 +67,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.login-mfa-form {
|
||||||
|
width: 420px;
|
||||||
|
padding: 50px 40px 45px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 2px 3px 7px rgb(0 0 0 / 20%);
|
||||||
|
.info-text {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #34495e;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.login-btn {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
.el-button {
|
||||||
|
width: 185px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,7 @@
|
|||||||
<div class="login-left">
|
<div class="login-left">
|
||||||
<img src="@/assets/images/login_left0.png" alt="login" />
|
<img src="@/assets/images/login_left0.png" alt="login" />
|
||||||
</div>
|
</div>
|
||||||
<div class="login-form">
|
<LoginForm ref="loginRef"></LoginForm>
|
||||||
<div class="login-logo">
|
|
||||||
<img class="login-icon" src="@/assets/images/logo.svg" alt="" />
|
|
||||||
<h2 class="logo-text">1Panel</h2>
|
|
||||||
</div>
|
|
||||||
<LoginForm ref="loginRef"></LoginForm>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-left: 50px" v-if="statusCode == -1">
|
<div style="margin-left: 50px" v-if="statusCode == -1">
|
||||||
@ -37,12 +31,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts" name="login">
|
<script setup lang="ts" name="login">
|
||||||
import LoginForm from './components/login-form.vue';
|
import LoginForm from './components/login-form.vue';
|
||||||
import { ref, onMounted, onBeforeMount } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import { loginStatus, entrance } from '@/api/modules/auth';
|
import { loginStatus, entrance } from '@/api/modules/auth';
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { GlobalStore } from '@/store';
|
|
||||||
const globalStore = GlobalStore();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
code: string;
|
code: string;
|
||||||
@ -69,11 +59,6 @@ const getStatus = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
if (globalStore.isLogin) {
|
|
||||||
router.push({ name: 'home' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getStatus();
|
getStatus();
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user