diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index c1dd884..c99d628 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -4,6 +4,7 @@
diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts
index 2317520..2b9cf17 100644
--- a/frontend/src/api/auth.ts
+++ b/frontend/src/api/auth.ts
@@ -3,7 +3,7 @@ import { getToken } from '@/utils/auth'
export interface LoginRequest {
username: string
- password: string
+ password?: string
}
export interface UserInfo {
@@ -20,9 +20,48 @@ export interface LoginResponse {
user: UserInfo
}
+export interface AuthConfig {
+ sso_enabled: boolean
+}
+
export const authApi = {
- login(_data: LoginRequest): Promise> {
- return Promise.reject(new Error('password login is disabled'))
+ async getConfig(): Promise> {
+ const response = await fetch('/auth/api/v1/config', {
+ headers: {
+ Accept: 'application/json',
+ },
+ })
+ const data = await response.json().catch(() => ({}))
+ if (!response.ok) {
+ throw new Error(data.error || `HTTP ${response.status}`)
+ }
+ return {
+ code: 0,
+ message: 'success',
+ data: {
+ sso_enabled: data.sso_enabled !== false,
+ },
+ }
+ },
+
+ async login(data: LoginRequest): Promise> {
+ const response = await fetch('/auth/api/v1/login', {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ username: data.username }),
+ })
+ const result = await response.json().catch(() => ({}))
+ if (!response.ok) {
+ throw new Error(result.error || `HTTP ${response.status}`)
+ }
+ return {
+ code: 0,
+ message: 'success',
+ data: result,
+ }
},
async logout(): Promise> {
diff --git a/frontend/src/api/request.ts b/frontend/src/api/request.ts
index c7fa184..6a6f390 100644
--- a/frontend/src/api/request.ts
+++ b/frontend/src/api/request.ts
@@ -61,7 +61,16 @@ request.interceptors.response.use(
if (status === 401) {
removeToken()
- redirectToSSO()
+ fetch('/auth/api/v1/config', { headers: { Accept: 'application/json' } })
+ .then((response) => response.json())
+ .then((data) => {
+ if (data.sso_enabled === false) {
+ window.location.assign('/login')
+ } else {
+ redirectToSSO()
+ }
+ })
+ .catch(() => redirectToSSO())
ElMessage.error(backendMessage || '未授权,请重新登录')
} else {
const message = backendMessage || httpMessageMap[status] || `请求失败 (${status})`
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
index cdb310f..e7e74ed 100644
--- a/frontend/src/router/index.ts
+++ b/frontend/src/router/index.ts
@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
import { getToken } from '@/utils/auth'
import { consumeSSOToken, redirectToSSO } from '@/utils/sso'
import { useAuthStore } from '@/stores/auth'
+import { authApi } from '@/api/auth'
const router = createRouter({
history: createWebHistory(),
@@ -113,6 +114,10 @@ router.beforeEach(async (to) => {
const token = authStore.token || getToken()
if (to.meta.requiresAuth !== false && !token) {
+ const { data } = await authApi.getConfig()
+ if (!data.sso_enabled) {
+ return { path: '/login', query: to.fullPath === '/' ? {} : { redirect: to.fullPath } }
+ }
redirectToSSO()
return false
}
@@ -121,6 +126,10 @@ router.beforeEach(async (to) => {
await authStore.refreshUser()
} catch {
authStore.clearAuth()
+ const { data } = await authApi.getConfig()
+ if (!data.sso_enabled) {
+ return { path: '/login', query: to.fullPath === '/' ? {} : { redirect: to.fullPath } }
+ }
redirectToSSO()
return false
}
diff --git a/frontend/src/views/auth/Login.vue b/frontend/src/views/auth/Login.vue
index 2d39019..bc08c66 100644
--- a/frontend/src/views/auth/Login.vue
+++ b/frontend/src/views/auth/Login.vue
@@ -9,32 +9,83 @@
{{ title }}
{{ subtitle }}
-
+
+
+
+
{{ buttonText }}