mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 11:27:17 +08:00
feat: 登录支持输入2fa验证码
This commit is contained in:
@@ -29,7 +29,8 @@ func MustLogin(t *gotext.Locale, session *sessions.Manager) func(next http.Handl
|
||||
"/api/user/key",
|
||||
"/api/user/login",
|
||||
"/api/user/logout",
|
||||
"/api/user/isLogin",
|
||||
"/api/user/is_login",
|
||||
"/api/user/is_2fa",
|
||||
"/api/dashboard/panel",
|
||||
}
|
||||
return func(next http.Handler) http.Handler {
|
||||
|
||||
@@ -12,7 +12,7 @@ type UserLogin struct {
|
||||
}
|
||||
|
||||
type UserIsTwoFA struct {
|
||||
Username string `uri:"username" validate:"required"`
|
||||
Username string `query:"username" validate:"required"`
|
||||
}
|
||||
|
||||
type UserCreate struct {
|
||||
|
||||
@@ -111,6 +111,7 @@ func (route *Http) Register(r *chi.Mux) {
|
||||
r.With(middleware.Throttle(5, time.Minute)).Post("/login", route.user.Login)
|
||||
r.Post("/logout", route.user.Logout)
|
||||
r.Get("/is_login", route.user.IsLogin)
|
||||
r.Get("/is_2fa", route.user.IsTwoFA)
|
||||
r.Get("/info", route.user.Info)
|
||||
})
|
||||
|
||||
|
||||
@@ -4,16 +4,19 @@ export default {
|
||||
// 公钥
|
||||
key: () => http.Get('/user/key'),
|
||||
// 登录
|
||||
login: (username: string, password: string, safe_login: boolean) =>
|
||||
login: (username: string, password: string, pass_code: string, safe_login: boolean) =>
|
||||
http.Post('/user/login', {
|
||||
username,
|
||||
password,
|
||||
pass_code,
|
||||
safe_login
|
||||
}),
|
||||
// 登出
|
||||
logout: () => http.Post('/user/logout'),
|
||||
// 是否登录
|
||||
isLogin: () => http.Get('/user/is_login'),
|
||||
// 是否2FA
|
||||
isTwoFA: (username: string) => http.Get('/user/is_2fa', { params: { username } }),
|
||||
// 获取用户信息
|
||||
info: () => http.Get('/user/info'),
|
||||
// 获取用户列表
|
||||
|
||||
@@ -19,12 +19,14 @@ interface LoginInfo {
|
||||
username: string
|
||||
password: string
|
||||
safe_login: boolean
|
||||
pass_code: string
|
||||
}
|
||||
|
||||
const loginInfo = ref<LoginInfo>({
|
||||
username: '',
|
||||
password: '',
|
||||
safe_login: true
|
||||
safe_login: true,
|
||||
pass_code: ''
|
||||
})
|
||||
|
||||
const localLoginInfo = getLocal('loginInfo') as LoginInfo
|
||||
@@ -37,11 +39,12 @@ const userStore = useUserStore()
|
||||
const themeStore = useThemeStore()
|
||||
const loging = ref<boolean>(false)
|
||||
const isRemember = useStorage('isRemember', false)
|
||||
const showTwoFA = ref(false)
|
||||
|
||||
const logo = computed(() => themeStore.logo || logoImg)
|
||||
|
||||
async function handleLogin() {
|
||||
const { username, password, safe_login } = loginInfo.value
|
||||
const { username, password, pass_code, safe_login } = loginInfo.value
|
||||
if (!username || !password) {
|
||||
window.$message.warning($gettext('Please enter username and password'))
|
||||
return
|
||||
@@ -56,6 +59,7 @@ async function handleLogin() {
|
||||
user.login(
|
||||
rsaEncrypt(username, String(unref(key))),
|
||||
rsaEncrypt(password, String(unref(key))),
|
||||
pass_code,
|
||||
safe_login
|
||||
)
|
||||
).onSuccess(async () => {
|
||||
@@ -82,6 +86,20 @@ async function handleLogin() {
|
||||
loging.value = false
|
||||
}
|
||||
|
||||
const isTwoFA = () => {
|
||||
const { username } = loginInfo.value
|
||||
if (!username) {
|
||||
return
|
||||
}
|
||||
useRequest(user.isTwoFA(username))
|
||||
.onSuccess(({ data }) => {
|
||||
showTwoFA.value = Boolean(data)
|
||||
})
|
||||
.onError(() => {
|
||||
showTwoFA.value = false
|
||||
})
|
||||
}
|
||||
|
||||
watch(isLogin, async () => {
|
||||
if (isLogin) {
|
||||
await addDynamicRoutes()
|
||||
@@ -113,6 +131,7 @@ watch(isLogin, async () => {
|
||||
autofocus
|
||||
class="h-50 items-center pl-10 text-16"
|
||||
:placeholder="$gettext('Username')"
|
||||
:on-blur="isTwoFA"
|
||||
/>
|
||||
</div>
|
||||
<div mt-30>
|
||||
@@ -126,6 +145,16 @@ watch(isLogin, async () => {
|
||||
@keydown.enter="handleLogin"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="showTwoFA" mt-30>
|
||||
<n-input
|
||||
v-model:value="loginInfo.pass_code"
|
||||
:maxlength="6"
|
||||
class="h-50 items-center pl-10 text-16"
|
||||
:placeholder="$gettext('2FA Code')"
|
||||
type="text"
|
||||
@keydown.enter="handleLogin"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div mt-20>
|
||||
<n-flex>
|
||||
|
||||
Reference in New Issue
Block a user