# 登录接口逻辑说明 ## 问题描述 原先的实现中,登录失败时后端会抛出 `UnauthorizedException`(HTTP 401),前端响应拦截器收到 401 后会自动清空 token 并跳转到登录页,这在登录页面本身会造成逻辑混乱。 ## 解决方案 ### 1. 后端修改 (`后端/src/auth/auth.controller.ts`) **修改前**: ```typescript async login(@Body() loginDto: LoginDto): Promise { const result = await this.authService.login(loginDto); return { code: 0, message: 'success', data: result }; } ``` - 如果 auth.service 抛出 `UnauthorizedException`,会直接返回 HTTP 401 状态码 **修改后**: ```typescript async login(@Body() loginDto: LoginDto): Promise { try { const result = await this.authService.login(loginDto); return { code: 0, message: '登录成功', data: result, }; } catch (error) { // 登录失败返回统一格式,不抛出 HTTP 异常 return { code: 401, message: error.message || '用户名或密码错误', data: null, }; } } ``` **关键变化**: - ✅ HTTP 状态码始终为 200 - ✅ 通过响应体的 `code` 字段区分成功(0)和失败(401) - ✅ 错误信息通过 `message` 字段返回 ### 2. 前端修改 (`管理后台/src/utils/request.ts`) **修改前**: ```typescript if (res.code !== 0 && res.code !== 200) { ElMessage.error(res.message || '请求失败') if (res.code === 401) { const userStore = useUserStore() userStore.logout() router.push('/login') } return Promise.reject(new Error(res.message || '请求失败')) } ``` - 所有 401 都会跳转登录页 **修改后**: ```typescript if (res.code !== 0 && res.code !== 200) { const isLoginRequest = response.config.url?.includes('/auth/login') if (res.code === 401 && !isLoginRequest) { ElMessage.error('登录已过期,请重新登录') const userStore = useUserStore() userStore.logout() router.push('/login') } else if (!isLoginRequest) { ElMessage.error(res.message || '请求失败') } return Promise.reject(new Error(res.message || '请求失败')) } ``` **关键变化**: - ✅ 区分登录请求和其他请求 - ✅ 登录接口的 401 不会触发自动跳转 - ✅ 登录接口的错误消息不在拦截器中显示(由登录页面处理) ### 3. 前端登录页面 (`管理后台/src/views/login/index.vue`) 保持原有的错误处理逻辑: ```typescript try { await userStore.login(loginForm.username, loginForm.password) ElMessage.success('登录成功') router.push('/') } catch (error: any) { const errorMessage = error.message || '登录失败,请检查用户名和密码' ElMessage.error(errorMessage) } ``` **关键点**: - ✅ 登录页面自己处理并显示错误信息 - ✅ 错误消息来自后端返回的 `message` 字段 ## 最终效果 ### 登录成功 ``` 请求: POST /api/auth/login 响应: { code: 0, message: '登录成功', data: { user: {...}, access_token: '...', refresh_token: '...' } } 结果: 显示"登录成功",跳转到首页 ``` ### 登录失败(用户名或密码错误) ``` 请求: POST /api/auth/login 响应: { code: 401, message: '用户名或密码错误', data: null } 结果: 显示"用户名或密码错误",停留在登录页 ``` ### 登录失败(账户被禁用) ``` 请求: POST /api/auth/login 响应: { code: 401, message: '账户已被禁用,请联系管理员', data: null } 结果: 显示"账户已被禁用,请联系管理员",停留在登录页 ``` ### 其他接口 Token 过期 ``` 请求: GET /api/case/list 响应: { code: 401, message: 'Unauthorized', data: null } 结果: 显示"登录已过期,请重新登录",清空 token,跳转到登录页 ``` ## 总结 这个修改确保了: 1. **登录接口**:失败时返回友好的错误信息,不会触发自动跳转 2. **其他接口**:Token 过期时自动清理状态并跳转到登录页 3. **用户体验**:错误提示清晰准确,不会出现重复提示或循环跳转