如何在Node应用中为Shopify Storefront API使用委托令牌
解决Shopify Storefront API限流:Node.js+AWS Lambda下用委托令牌传递客户端IP
核心逻辑
Shopify的委托令牌(Delegated Access Token)允许后端服务代表客户端发起Storefront API请求,同时通过请求头传递客户端真实IP,让Shopify基于客户端IP做限流判断,而非Lambda的固定出口IP。关键是两步:生成带权限的委托令牌,请求时附加客户端IP头。
步骤1:生成委托令牌
委托令牌需通过Shopify Admin API创建,指定权限、有效期和客户端标识符(用来关联请求发起者)。
代码示例(Node.js + Axios)
const axios = require('axios'); async function generateDelegatedToken(shopDomain, adminAccessToken, clientId) { try { const res = await axios.post( `https://${shopDomain}/admin/api/2024-07/access_tokens/delegate.json`, { delegate_access_token: { subject: clientId, // 用客户端会话ID/用户ID作为标识 permissions: ['write_customers'], // 密码重置需该权限 expires_in: 3600 // 令牌有效期1小时,可按需调整 } }, { headers: { 'X-Shopify-Access-Token': adminAccessToken, 'Content-Type': 'application/json' } } ); return res.data.delegate_access_token.token; } catch (err) { console.error('生成委托令牌失败:', err.response?.data || err.message); throw err; } }
步骤2:传递客户端IP发起Storefront请求
从Lambda事件中提取客户端真实IP,结合委托令牌调用Storefront API,同时添加Shopify-User-IP头(Shopify优先识别这个)。
提取客户端IP(Lambda APIGateway场景)
function getClientRealIp(event) { // 优先取X-Forwarded-For(CDN转发场景) const forwardedFor = event.headers?.['X-Forwarded-For']; if (forwardedFor) { // 格式通常为 "客户端IP, 代理IP1, 代理IP2",取第一个 return forwardedFor.split(',')[0].trim(); } // 直接取Lambda自带的源IP return event.requestContext?.http?.sourceIp; }
密码重置请求示例(Storefront GraphQL API)
async function resetCustomerPassword(shopDomain, delegatedToken, clientIp, email) { const mutation = ` mutation CustomerRecover($email: String!) { customerRecover(email: $email) { customerUserErrors { message } } } `; try { const res = await axios.post( `https://${shopDomain}/api/2024-07/graphql.json`, { query: mutation, variables: { email } }, { headers: { 'Authorization': `Bearer ${delegatedToken}`, 'Content-Type': 'application/json', 'Shopify-User-IP': clientIp, // 核心:传递客户端真实IP 'X-Forwarded-For': clientIp // 备选,兼容部分场景 } } ); return res.data; } catch (err) { console.error('密码重置请求失败:', err.response?.data || err.message); throw err; } }
优化建议
- 令牌缓存:委托令牌有效期内可缓存(比如用DynamoDB或Lambda内存),避免重复调用Admin API
- 权限最小化:令牌权限只申请需要的(比如密码重置仅需
write_customers),降低安全风险 - 错误重试:若仍触发限流,可针对客户端IP做本地重试延迟,避免频繁请求Shopify
内容的提问来源于stack exchange,提问作者Untoughtful
相关产品推荐
相关产品推荐

