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

SvelteKit如何携带Access Token调用受SSO保护的外部API

SvelteKit对接SSO保护的Express API的鉴权方案

问题背景

现有一套基于Node.js Express搭建的API服务,支持图片、视频等多类型文件上传、获取,同时可返回标准JSON格式响应。需要将SvelteKit应用对接至该API,但这套API受SSO安全策略保护,所有请求必须携带有效访问令牌。
目前已在SvelteKit端通过OIDC协议的SSO流程成功获取访问令牌,先后尝试三种实现方案均存在缺陷:

  • 方案一:通过Service Worker拦截所有发往目标API的请求,自动注入访问令牌
    存在问题:Service Worker仅在生产构建环境生效,开发环境无法使用,每次调试都执行生产构建流程会大幅降低开发效率。
  • 方案二:所有请求先发送至SvelteKit后端服务,由后端携带访问令牌转发至目标API
    存在问题:该方案最初仅支持普通请求,不支持流传输;近期虽已有相关功能支持的进展,但缺乏官方文档与可参考的使用示例,同时会额外消耗服务端带宽与计算资源,理想状态下文件类请求应当直接从浏览器发往API端,不需要经过SvelteKit服务端中转。
  • 方案三:使用Hooks中的externalFetch能力,修改或替换服务端运行(含预渲染阶段)load函数内发起的外部资源fetch请求
    存在问题:该能力无法覆盖图片src属性这类由浏览器直接发起的静态资源请求。
    实测新版SvelteKit已将内置的node-fetch替换为Undici,流传输功能可正常使用,能够稳定实现后端请求转发,这种方式在开发环境下使用体验较好,但并非生产环境的最优方案,可根据运行环境组合使用不同方案。

推荐实现思路

采用环境分层+按请求类型分流的组合策略,兼顾开发体验、生产性能与鉴权安全性,不需要强制依赖单一方案:

基础层:统一请求封装

首先封装通用API请求客户端,覆盖所有主动发起的JSON请求、文件上传请求,自动注入访问令牌,避免重复写鉴权逻辑:

// src/lib/apiClient.js
const API_BASE = import.meta.env.VITE_API_BASE;

export async function apiRequest(path, options = {}) {
  const token = localStorage.getItem('sso_access_token');
  return fetch(`${API_BASE}${path}`, {
    ...options,
    headers: {
      ...options.headers,
      Authorization: `Bearer ${token}`
    }
  });
}

开发环境:服务端代理兜底

开发环境优先保障热更效率,不启用Service Worker,用服务端转发覆盖所有场景:

  • 所有load函数内的数据请求,通过hooks.server.js中的externalFetch钩子自动注入服务端存储的SSO令牌,不需要额外业务代码处理
  • 图片、视频这类由标签直接发起的静态资源请求,统一走SvelteKit通用代理路由,利用Undici的流能力直接透传API响应,不会把文件全量缓存到SvelteKit服务端内存,资源损耗极低。代理路由示例:
// src/routes/api/dev-proxy/[...path]/+server.js
export async function GET({ params, request, locals }) {
  // 提前在hooks中从session解析出SSO令牌挂载到locals
  const token = locals.accessToken;
  const path = params.path;
  const search = request.url.split('?')[1] ? `?${request.url.split('?')[1]}` : '';
  const targetRes = await fetch(`${import.meta.env.VITE_API_BASE}/${path}${search}`, {
    headers: { Authorization: `Bearer ${token}` },
    duplex: 'half'
  });
  return new Response(targetRes.body, {
    headers: targetRes.headers
  });
}

开发环境下静态资源的src属性统一指向该代理路由即可,不需要额外处理鉴权。

生产环境:客户端直连优先

生产环境优先保障性能,关闭服务端代理,启用Service Worker做全量请求拦截:

  • 生产构建时自动注册Service Worker,拦截所有指向API域名的请求——不管是主动发起的fetch请求,还是img、video标签触发的静态资源请求,统一自动注入客户端存储的访问令牌,所有请求直连API服务,完全不占用SvelteKit服务端资源
  • 增加降级逻辑:Service Worker未激活的极端场景(比如用户浏览器禁用SW、首次访问SW尚未注册完成),静态资源临时fallback到服务端代理路由,等SW激活后自动切回直连模式,保证页面可用性

边界场景处理

  • 令牌过期:在请求客户端、Service Worker、代理路由三层统一拦截401响应,自动触发SSO令牌刷新流程,刷新失败则跳转SSO登录页
  • 大文件上传:不管开发还是生产环境,大文件上传统一走客户端直传,通过封装的apiRequest注入令牌,不经过代理,避免占用服务端带宽
  • 预渲染页面:构建阶段预渲染的页面如果需要引用API静态资源,提前在externalFetch钩子中完成鉴权拉取资源,做静态化处理,用户访问时不需要额外请求API

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:54:16