登录验证码接入

This commit is contained in:
biss committed 2026-09-11 22:05:07 +08:00
1 parent ae075bda6d
commit f489a3553c
15 files changed
+471 -19

No files matched your search

+12 -15
View File
@@ -20,14 +20,16 @@ const http = axios.create({
timeout: 15000,
})
function isAuthenticationRequest(url?: string) {
return url?.startsWith('/auth/login') ||
url?.endsWith('/auth/refresh') ||
url?.endsWith('/auth/logout') ||
url?.endsWith('/auth/sso/exchange') ||
url?.endsWith('/auth/sso/bind')
}
http.interceptors.request.use(async (config) => {
const isAuthenticationRequest =
config.url?.endsWith('/auth/login') ||
config.url?.endsWith('/auth/refresh') ||
config.url?.endsWith('/auth/logout') ||
config.url?.endsWith('/auth/sso/exchange') ||
config.url?.endsWith('/auth/sso/bind')
if (!isAuthenticationRequest && !config.skipAuthSession) {
if (!isAuthenticationRequest(config.url) && !config.skipAuthSession) {
const activeToken = await refreshIfNeeded(true)
if (activeToken) markActivity()
}
@@ -39,15 +41,10 @@ http.interceptors.request.use(async (config) => {
http.interceptors.response.use(
(response) => response,
async (error) => {
const isAuthenticationRequest =
error.config?.url?.endsWith('/auth/login') ||
error.config?.url?.endsWith('/auth/refresh') ||
error.config?.url?.endsWith('/auth/logout') ||
error.config?.url?.endsWith('/auth/sso/exchange') ||
error.config?.url?.endsWith('/auth/sso/bind')
const authenticationRequest = isAuthenticationRequest(error.config?.url)
const retryableConfig = error.config as
(typeof error.config & { _jiaowuRetried?: boolean }) | undefined
if (error.response?.status === 401 && !isAuthenticationRequest && !error.config?.skipAuthSession &&
if (error.response?.status === 401 && !authenticationRequest && !error.config?.skipAuthSession &&
!retryableConfig?._jiaowuRetried) {
const token = await refreshAuthSession()
if (token && retryableConfig) {
@@ -56,7 +53,7 @@ http.interceptors.response.use(
return http.request(retryableConfig)
}
}
if (error.response?.status === 401 && !isAuthenticationRequest && !error.config?.skipAuthSession) {
if (error.response?.status === 401 && !authenticationRequest && !error.config?.skipAuthSession) {
clearAuthSession()
goLogin(location.pathname + location.search + location.hash)
}
+13
View File
@@ -0,0 +1,13 @@
import FingerprintJS from '@fingerprintjs/fingerprintjs'
const fingerprint = FingerprintJS.load()
/** A pseudonymous, client-generated identifier used only to bind short-lived login challenges. */
export async function getLoginDeviceId(): Promise<string> {
try {
return (await fingerprint).get().then((result) => result.visitorId)
} catch {
// Privacy extensions may block fingerprinting. The captcha remains usable with IP/session binding.
return ''
}
}
+1
View File
@@ -61,6 +61,7 @@ declare module 'vue' {
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect']
ElUpload: typeof import('element-plus/es')['ElUpload']
LoginCaptcha: typeof import('./components/LoginCaptcha.vue')['default']
NativePlaceCascader: typeof import('./components/NativePlaceCascader.vue')['default']
NotificationRichTextEditor: typeof import('./components/NotificationRichTextEditor.vue')['default']
PerformanceReportPanel: typeof import('./components/PerformanceReportPanel.vue')['default']
Loaded 3 of 15 files, more files were not shown because too many files have changed in this diff. Show more