Fix auth security: add request timeout, safe redirects, and memory-only token support.
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
import Brand from '@/components/Brand.vue'
|
||||
import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { api } from '@/utils/request'
|
||||
import { ApiError } from '@/types/api'
|
||||
import type { UserInfo } from '@/stores/user'
|
||||
|
||||
const formState = reactive({
|
||||
username: '',
|
||||
@@ -29,33 +32,33 @@ const handleSubmit = async () => {
|
||||
await formRef.value.validate()
|
||||
loading.value = true
|
||||
|
||||
const response = await fetch('/api/auth/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
username: formState.username,
|
||||
password: formState.password,
|
||||
}),
|
||||
const data = await api.post<{
|
||||
access_token: string
|
||||
refresh_token: string
|
||||
user: UserInfo
|
||||
}>('/api/auth/login', {
|
||||
username: formState.username,
|
||||
password: formState.password,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
userStore.setToken(data.access_token, data.refresh_token, formState.remember)
|
||||
userStore.setUser(data.user)
|
||||
|
||||
if (data.code === 0) {
|
||||
userStore.setToken(data.data.access_token, data.data.refresh_token)
|
||||
userStore.setUser(data.data.user)
|
||||
|
||||
message.success('登录成功!')
|
||||
const redirect = (route.query.redirect as string) || '/'
|
||||
setTimeout(() => {
|
||||
router.push(redirect)
|
||||
}, 500)
|
||||
} else {
|
||||
message.error(data.message || '登录失败,请重试')
|
||||
}
|
||||
message.success('登录成功!')
|
||||
// 校验 redirect 防止开放重定向漏洞
|
||||
const redirect = (route.query.redirect as string) || '/'
|
||||
const safeRedirect = redirect.startsWith('/') && !redirect.includes('//') ? redirect : '/'
|
||||
setTimeout(() => {
|
||||
router.push(safeRedirect)
|
||||
}, 500)
|
||||
} catch (error: unknown) {
|
||||
if (error && typeof error === 'object' && 'errorFields' in error) {
|
||||
return
|
||||
}
|
||||
if (error instanceof ApiError) {
|
||||
message.error(error.message)
|
||||
return
|
||||
}
|
||||
console.error('登录错误:', error)
|
||||
message.error('登录失败,请检查网络连接')
|
||||
} finally {
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
import Brand from '@/components/Brand.vue'
|
||||
import { UserOutlined, LockOutlined, MailOutlined } from '@ant-design/icons-vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { api } from '@/utils/request'
|
||||
import { ApiError } from '@/types/api'
|
||||
import type { UserInfo } from '@/stores/user'
|
||||
|
||||
const formState = reactive({
|
||||
username: '',
|
||||
@@ -47,38 +50,36 @@ const handleSubmit = async () => {
|
||||
await formRef.value.validate()
|
||||
loading.value = true
|
||||
|
||||
const response = await fetch('/api/auth/register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
username: formState.username,
|
||||
email: formState.email,
|
||||
password: formState.password,
|
||||
}),
|
||||
const data = await api.post<{
|
||||
access_token?: string
|
||||
refresh_token?: string
|
||||
user?: UserInfo
|
||||
}>('/api/auth/register', {
|
||||
username: formState.username,
|
||||
email: formState.email,
|
||||
password: formState.password,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (data.code === 0) {
|
||||
// 注册成功后自动设置 token(如果后端返回)
|
||||
if (data.data?.access_token) {
|
||||
userStore.setToken(data.data.access_token, data.data.refresh_token)
|
||||
if (data.data.user) {
|
||||
userStore.setUser(data.data.user)
|
||||
}
|
||||
// 注册成功后自动设置 token(如果后端返回)
|
||||
if (data?.access_token) {
|
||||
userStore.setToken(data.access_token, data.refresh_token!)
|
||||
if (data.user) {
|
||||
userStore.setUser(data.user)
|
||||
}
|
||||
|
||||
message.success('注册成功!即将跳转到登录页...')
|
||||
setTimeout(() => {
|
||||
router.push('/login')
|
||||
}, 1500)
|
||||
} else {
|
||||
message.error(data.message || '注册失败,请重试')
|
||||
}
|
||||
|
||||
message.success('注册成功!即将跳转到登录页...')
|
||||
setTimeout(() => {
|
||||
router.push('/login')
|
||||
}, 1500)
|
||||
} catch (error: unknown) {
|
||||
if (error && typeof error === 'object' && 'errorFields' in error) {
|
||||
return
|
||||
}
|
||||
if (error instanceof ApiError) {
|
||||
message.error(error.message)
|
||||
return
|
||||
}
|
||||
console.error('注册错误:', error)
|
||||
message.error('注册失败,请检查网络连接')
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user