NextJS搭配Supabase鉴权时如何为Urql客户端设置Authorization请求头
解决方案
首先明确:绝对不要移除Cookie的HttpOnly属性,这是防范XSS攻击窃取用户身份凭证的核心安全机制,移除会带来严重的安全风险。
你遇到的问题可以分客户端请求、服务端请求两种场景分别处理,不需要手动读取HttpOnly Cookie:
1. 客户端侧请求处理
你已经在配置里加了credentials: 'include',浏览器发起请求时会自动携带所有同域的HttpOnly Cookie,你的GraphQL后端可以直接从请求的Cookie字段中读取Supabase的身份凭证,无需你手动在前端把token塞入Authorization头。
如果你的后端确实要求必须从Authorization头获取token,可以使用Urql官方的@urql/exchange-auth交换器,配合Supabase客户端获取token:
首先安装依赖:
npm install @urql/exchange-auth
然后修改urql.ts的配置:
import { createClient, ssrExchange, dedupExchange, fetchExchange } from 'urql'; import { cacheExchange } from '@urql/exchange-graphcache'; import { devtoolsExchange } from '@urql/devtools'; import { authExchange } from '@urql/exchange-auth'; // 引入你项目里初始化好的Supabase客户端 import { supabase } from './supabase'; const isServerSide = typeof window === 'undefined'; const ssrCache = ssrExchange({ isClient: !isServerSide, initialState: !isServerSide ? window.__URQL_DATA__ : undefined, }); const client = createClient({ url: '/api/graphql', exchanges: [ devtoolsExchange, dedupExchange, cacheExchange({}), authExchange(async utils => { // 客户端侧通过Supabase客户端获取session const { data: { session } } = await supabase.auth.getSession(); return { addAuthToOperation(operation) { if (!session?.access_token) return operation; return utils.appendHeaders(operation, { Authorization: `Bearer ${session.access_token}`, }); }, willAuthError() { return false }, didAuthError() { return false }, async refreshAuth() {}, }; }), ssrCache, fetchExchange, ], fetchOptions: () => { return { credentials: 'include', }; }, }); export { client, ssrCache };
2. 服务端侧请求处理
在NextJS服务端渲染场景(Pages Router的getServerSideProps、App Router的服务端组件),你需要从传入的请求头中提取Cookie,再初始化对应请求的Urql客户端实例,直接透传Cookie给后端即可:
以Pages Router的getServerSideProps为例:
import { createClient, ssrExchange, dedupExchange, fetchExchange } from 'urql'; import { cacheExchange } from '@urql/exchange-graphcache'; import { parse } from 'cookie'; export async function getServerSideProps(context) { const ssrCache = ssrExchange({ isClient: false }); const serverClient = createClient({ url: '/api/graphql', exchanges: [dedupExchange, cacheExchange({}), ssrCache, fetchExchange], fetchOptions: { credentials: 'include', headers: { // 直接把客户端传来的Cookie透传给后端即可,不需要解析token Cookie: context.req.headers.cookie || '', }, }, }); // 这里执行服务端的GraphQL查询逻辑... return { props: { urqlState: ssrCache.extractData(), }, }; }
内容的提问来源于stack exchange,提问作者J. Jackson
相关产品推荐
相关产品推荐

