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

如何解决NextJS 14 App Router中Header组件刷新后Logout按钮消失问题

解决页面刷新后登录状态丢失的问题

问题核心是useState存储的用户状态在页面刷新时会重置,需要在组件初始化时从后端验证当前登录状态并恢复用户信息。

步骤1:添加登录状态验证与初始化逻辑

修改AdminAuthContext代码,新增状态验证函数,并通过useEffect在组件挂载时自动触发:

"use client";

import { createContext, useContext, useEffect, useState } from "react";
import { useRouter } from 'next/navigation';

const host = process.env.NEXT_PUBLIC_API_HOST;
export const AdminAuthContext = createContext({});
export const AdminAuthProvider = ({ children }) => {
    const router = useRouter();
    const [user, setUser] = useState(null);

    // 验证当前登录状态,从后端拉取用户信息
    const checkAuthStatus = async () => {
        try {
            const response = await fetch(`${host}/api/admin/me`, {
                cache: "no-store",
                credentials: "include", // 携带Cookie中的JWT Token
            });

            if (response.ok) {
                const res = await response.json();
                setUser(res.username); // 恢复用户状态
            } else {
                setUser(null); // 未登录则清空状态
            }
        } catch (error) {
            console.error("验证登录状态失败:", error);
            setUser(null);
        }
    };

    // 组件挂载时自动检查登录状态
    useEffect(() => {
        checkAuthStatus();
    }, []);

    const doAdminLogin = async (email, password) => {
        const request = await fetch(`${host}/api/admin/login`, {
            cache: "no-store",
            method: "POST",
            credentials: "include",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ email, password }),
        });

        if (!request.ok) {
            console.error('Login failed');
            throw new Error("Error logging in");
        }

        const res = await request.json();
        setUser(res.username);
        router.push('/private/admin/dashboard');
    };

    const doAdminLogout = async () => {
        try {
            const request = await fetch(`${host}/api/admin/logout`, {
                cache: "no-store",
                method: "POST",
                credentials: "include",
            });

            if (request.ok) {
                setUser(null); // 登出后清空用户状态
                router.push('/'); // 跳转到首页或登录页
            }
        } catch (error) {
            console.error("登出失败:", error);
        }
    };

    return (
        <AdminAuthContext.Provider value={{ user, doAdminLogin, doAdminLogout }}>
            {children}
        </AdminAuthContext.Provider>
    );
};

export function useAdminAuthContext() {
    return useContext(AdminAuthContext);
}

步骤2:确保AdminAuthProvider全局生效

检查你的GlobalProvider是否已经包裹AdminAuthProvider,如果没有,修改GlobalProvider代码:

// _lib/global-provider.js
"use client";

import { AdminAuthProvider } from "./admin-auth-provider";

export function GlobalProvider({ children }) {
    return (
        <AdminAuthProvider>
            {/* 其他全局提供者(如有) */}
            {children}
        </AdminAuthProvider>
    );
}

步骤3:后端实现状态验证接口

Spring Boot需要新增/api/admin/me接口,用于验证Cookie中的JWT Token并返回当前用户信息:

@RestController
@RequestMapping("/api/admin")
public class AdminController {

    @GetMapping("/me")
    public ResponseEntity<Map<String, String>> getCurrentUser(HttpServletRequest request) {
        // 从Cookie中提取JWT Token
        String jwtToken = null;
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("JWT_TOKEN".equals(cookie.getName())) { // 替换为你的Cookie名称
                    jwtToken = cookie.getValue();
                    break;
                }
            }
        }

        // 验证Token有效性
        if (jwtToken == null || !JwtUtil.isValidToken(jwtToken)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }

        // 提取用户名并返回
        String username = JwtUtil.extractUsername(jwtToken);
        Map<String, String> response = new HashMap<>();
        response.put("username", username);
        return ResponseEntity.ok(response);
    }
}

关键说明

  • credentials: "include":确保请求携带Cookie,后端才能验证JWT Token的有效性
  • checkAuthStatus函数:页面刷新后自动触发,从后端拉取最新登录状态,恢复用户信息
  • 完善登出逻辑:调用后端接口后清空user状态并跳转,避免状态不一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:26:05