You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Django REST Framework中JWT过期后用户未自动登出问题

JWT令牌过期后前端未自动登出的解决方案

问题根源

你当前仅在登录时存储JWT令牌,但未实现令牌过期监听和API请求错误拦截,导致access token过期后前端无法感知并触发登出逻辑。


具体解决步骤

1. 登录时设置过期定时器,主动触发登出

登录解析access token的过期时间,设置定时器,到期后自动清除令牌并跳转登录页:

let loginUser = async (e )=> {
    e.preventDefault()
    try {
        const res = await axios.post('http://127.0.0.1:8000/api/token/', {
            headers: {
                'Content-type': 'application/json'
            },
            username: e.target.username.value,
            password: e.target.password.value
        })
        const authTokens = res.data
        setAuthTokens(authTokens)
        const userData = jwt_decode(authTokens.access)
        setUser(userData)
        localStorage.setItem('authTokens', JSON.stringify(authTokens))
        
        // 计算过期剩余时间,设置自动登出定时器
        const expiresIn = userData.exp * 1000 - Date.now()
        setTimeout(() => {
            localStorage.removeItem('authTokens')
            setAuthTokens(null)
            setUser(null)
            navigate('/login')
        }, expiresIn)
        
        navigate('/')
    } catch {
        alert('登录失败,请检查账号密码')
    }
}

2. 全局拦截API请求,处理401错误

用axios拦截器统一捕获401响应(令牌过期/无效),避免页面刷新后定时器丢失导致的漏判:

// 在axios初始化文件或App组件中添加拦截器
axios.interceptors.response.use(
    response => response,
    error => {
        if (error.response?.status === 401) {
            // 清除令牌并强制跳转登录页
            localStorage.removeItem('authTokens')
            window.location.href = '/login'
        }
        return Promise.reject(error)
    }
)

3. 页面刷新时重新初始化定时器

页面刷新后之前的定时器会消失,需在应用初始化时检查本地存储的令牌状态:

useEffect(() => {
    const storedTokens = localStorage.getItem('authTokens')
    if (storedTokens) {
        const authTokens = JSON.parse(storedTokens)
        const userData = jwt_decode(authTokens.access)
        const expiresIn = userData.exp * 1000 - Date.now()
        
        if (expiresIn > 0) {
            // 令牌未过期,重新设置定时器
            setTimeout(() => {
                localStorage.removeItem('authTokens')
                setAuthTokens(null)
                setUser(null)
                navigate('/login')
            }, expiresIn)
        } else {
            // 令牌已过期,直接登出
            localStorage.removeItem('authTokens')
            setAuthTokens(null)
            setUser(null)
            navigate('/login')
        }
    }
}, [navigate])

4. 补全Django端JWT配置

你当前的SIMPLE_JWT配置缺少闭合括号,补全后确保后端返回正确的401状态码:

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(seconds=4),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=90),
    "ROTATE_REFRESH_TOKENS": True,
    "BLACKLIST_AFTER_ROTATION": True,
    "UPDATE_LAST_LOGIN": False,
}

可选优化:自动刷新令牌

若需避免用户频繁登录,可在access token过期前调用/api/token/refresh/接口获取新令牌,更新本地存储并重置定时器,实现无感续期。

内容的提问来源于stack exchange,提问作者Tassaras Tassakos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:06:09