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

如何在+page.ts中兼顾SSR与CSR从Cookie获取认证令牌?

在通用load函数中跨环境获取Cookie令牌

要在同时支持SSR和CSR的load函数中,在服务端环境获取Cookie中的access/refresh tokens,且不强制使用SSR(无需依赖+page.server.ts),可以按以下方式实现:

1. 编写环境适配的Cookie解析函数

创建一个能同时在服务端和客户端运行的函数,根据当前环境从对应位置读取并解析Cookie:

import { isServer } from '$app/environment';

/**
 * 从Cookie中提取access和refresh令牌
 * @param request 服务端环境下传入的Request对象
 */
function extractTokens(request?: Request) {
    let cookieString = '';

    if (isServer) {
        if (!request) throw new Error('Request must be provided in server context');
        cookieString = request.headers.get('cookie') || '';
    } else {
        cookieString = document.cookie;
    }

    // 解析Cookie字符串为键值对
    const cookiePairs = cookieString.split(';').map(pair => pair.trim());
    const cookies: Record<string, string> = {};

    for (const pair of cookiePairs) {
        const [key, value] = pair.split('=', 2);
        if (key && value) {
            cookies[key] = decodeURIComponent(value);
        }
    }

    return {
        accessToken: cookies.access_token,
        refreshToken: cookies.refresh_token
    };
}

2. 修改load函数逻辑

在load函数中,根据当前环境传入对应的参数调用解析函数,并基于令牌完成身份校验和数据请求:

import type { PageLoad } from './$types';
import { isServer, browser } from '$app/environment';
import { goto, redirect } from '$app/navigation';

export const load: PageLoad = async (obj) => {
    // 提取令牌:服务端传入request,客户端无需参数
    const { accessToken, refreshToken } = extractTokens(isServer ? obj.request : undefined);

    // 调整身份校验函数,传入令牌进行验证
    if (await ifAuthenticated(accessToken, refreshToken)) {
        // 请求第三方服务时携带令牌
        const response = await fetch('https://third-party-service.com/api/data', {
            headers: {
                Authorization: `Bearer ${accessToken}`
            }
        });
        
        if (!response.ok) {
            // 处理请求失败逻辑,比如令牌过期时刷新令牌
            throw new Error('Failed to fetch data');
        }

        return await response.json();
    } else {
        // 未认证时跳转登录页,区分服务端和客户端逻辑
        if (browser) {
            goto('/login');
        } else {
            throw redirect(307, '/login');
        }
    }
};

核心要点

  • 保持load函数的通用性:不使用+page.server.ts,这样客户端导航(比如点击路由链接)时会走CSR,只有首次访问或页面刷新时触发SSR。
  • 服务端环境必须通过request.headers获取Cookie:服务端没有document对象,直接读取会导致运行时错误。
  • 令牌安全:确保Cookie配置了HttpOnly、Secure和SameSite属性,防止XSS和CSRF攻击。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:42:40