如何为EventSource发起的SSE请求附加JWT授权请求头
首先明确核心限制:浏览器原生EventSource API 没有提供自定义请求头的配置能力,无法直接在初始化时传入headers参数,你可以根据项目的安全要求、技术栈选择以下任意一种方案实现SSE接口鉴权:
方案1:URL查询参数传递token(零依赖快速实现)
这是原生EventSource下改造成本最低的方案,直接把鉴权token拼接到SSE接口的URL参数中,后端从query字段读取token做校验即可:// React组件中的初始化示例 const sseConnection = new EventSource( `${process.env.REACT_APP_API_BASE}/sse/stream?token=${encodeURIComponent(authSession.access_token)}` );注意该方案存在安全隐患:token会明文出现在URL中,可能被浏览器访问记录、服务器访问日志、中间代理日志留存,仅适合内部系统、低安全要求场景使用。
方案2:Cookie自动携带鉴权凭证(安全性更高)
如果你的鉴权体系支持Cookie模式,EventSource发起请求时默认会自动携带同源下的Cookie,你只需要提前将鉴权token写入带HttpOnly、Secure、SameSite标记的安全Cookie中,无需修改EventSource初始化代码,后端直接从Cookie中读取token校验即可。如果是跨域场景,需要开启跨域凭证携带配置:const sseConnection = new EventSource( `${process.env.REACT_APP_API_BASE}/sse/stream`, { withCredentials: true } );方案3:基于Fetch API自定义SSE客户端(支持任意自定义请求头)
如果你必须按照规范把Authorization放在请求头中传递,就放弃原生EventSource,直接基于浏览器原生fetch+ReadableStream实现SSE协议解析,完全支持自定义请求头,核心实现代码如下:const initSSE = async () => { const resp = await fetch(`${process.env.REACT_APP_API_BASE}/sse/stream`, { method: 'GET', headers: { 'Authorization': `Bearer ${authSession.access_token}`, 'Accept': 'text/event-stream' } }); if (!resp.ok || !resp.body) { throw new Error(`SSE连接异常,状态码:${resp.status}`); } const reader = resp.body.getReader(); const textDecoder = new TextDecoder('utf-8'); let pendingBuffer = ''; // 持续读取流内容 while (true) { const { done, value } = await reader.read(); if (done) break; pendingBuffer += textDecoder.decode(value, { stream: true }); const eventLines = pendingBuffer.split('\n'); // 保留未接收完整的残差行,等待下次数据到达后拼接 pendingBuffer = eventLines.pop(); for (const line of eventLines) { const content = line.trim(); if (content.startsWith('data:')) { const eventData = content.slice(5).trim(); // 此处替换为你自己的消息处理逻辑,对齐原生EventSource的message事件 console.log('收到SSE推送数据:', JSON.parse(eventData)); } } } }; // 组件挂载时建立连接 useEffect(() => { initSSE().catch(err => console.error('SSE连接失败:', err)); }, [authSession.access_token]);如果不想自己处理流解析、断线重连等逻辑,可以直接使用成熟的第三方SSE客户端库(比如微软开源的
@microsoft/fetch-event-source),API设计和原生EventSource基本对齐,原生支持自定义请求头、断线重连等能力。
内容的提问来源于stack exchange,提问作者Rylan Schaeffer

