task-26(会话/菜单/权限): 实现 401 登录跳转行为防循环守卫
401 统一跳 /login 并携带目标路径;新增纯函数守卫 isLoginLocation/ isAuthEndpointRequest/shouldRedirectUnauthorized:已处登录页或失败请求即 登录端点时不再二次跳转,避免登录页死循环与吞掉登录失败反馈。http 层 success/error 两支均带失败请求 URL 过守卫后再跳转。envelope/http 单测 8 用例 + 全量 179 单测 + vue-tsc/vite build 通过。
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { isUnauthorized, loginRedirectTarget } from './envelope'
|
||||
import { isUnauthorized, loginRedirectTarget, shouldRedirectUnauthorized } from './envelope'
|
||||
|
||||
export { unwrap } from './envelope'
|
||||
|
||||
@@ -9,8 +9,10 @@ export const http = axios.create({
|
||||
timeout: 30_000,
|
||||
})
|
||||
|
||||
function redirectToLogin(): void {
|
||||
function redirectToLogin(requestUrl?: string): void {
|
||||
if (typeof window === 'undefined') return
|
||||
// 已在登录页或失败请求即登录端点时不再跳转,避免登录页循环与吞掉登录失败反馈。
|
||||
if (!shouldRedirectUnauthorized(window.location.pathname, requestUrl)) return
|
||||
const target = loginRedirectTarget(window.location)
|
||||
window.location.assign(`/login?redirect=${target}`)
|
||||
}
|
||||
@@ -18,11 +20,13 @@ function redirectToLogin(): void {
|
||||
http.interceptors.response.use(
|
||||
(response) => {
|
||||
// Java 未登录以 HTTP 200 + body.code=401 返回,需统一按未登录处理。
|
||||
if (isUnauthorized(response.data)) redirectToLogin()
|
||||
if (isUnauthorized(response.data)) redirectToLogin(response.config?.url)
|
||||
return response
|
||||
},
|
||||
(error) => {
|
||||
if (error?.response?.status === 401 || isUnauthorized(error?.response?.data)) redirectToLogin()
|
||||
if (error?.response?.status === 401 || isUnauthorized(error?.response?.data)) {
|
||||
redirectToLogin(error?.config?.url)
|
||||
}
|
||||
return Promise.reject(error)
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user