PersonalWebApplication/Client/src/hooks/useAuth.ts

63 lines
1.9 KiB
TypeScript
Raw Normal View History

import { useCallback, useState } from 'react'
import { login as loginRequest } from '../api/auth'
// localStorage 键:记住登录态时把会话写在这里,刷新后仍处于登录态。
const STORAGE_KEY = 'ip.auth'
interface Session {
username: string
token: string
}
function loadSession(): Session | null {
try {
const raw = localStorage.getItem(STORAGE_KEY)
if (!raw) return null
const parsed = JSON.parse(raw) as Partial<Session>
if (typeof parsed.username === 'string' && typeof parsed.token === 'string') {
return { username: parsed.username, token: parsed.token }
}
} catch {
// 解析失败(被手动改坏等)当作未登录
}
return null
}
export interface Auth {
/** 已登录则为当前用户名,否则为 null */
username: string | null
/** 校验凭据remember 为 true 时持久化到 localStorage */
signIn: (username: string, password: string, remember: boolean) => Promise<void>
/** 退出登录并清除持久化会话 */
signOut: () => void
}
/**
* localStorage
*
*/
export function useAuth(): Auth {
const [session, setSession] = useState<Session | null>(loadSession)
const signIn = useCallback(
async (username: string, password: string, remember: boolean) => {
const result = await loginRequest(username, password)
const next: Session = { username: result.username, token: result.token }
setSession(next)
if (remember) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(next))
} else {
localStorage.removeItem(STORAGE_KEY)
}
},
[],
)
const signOut = useCallback(() => {
setSession(null)
localStorage.removeItem(STORAGE_KEY)
}, [])
return { username: session?.username ?? null, signIn, signOut }
}