Expo托管React Native应用如何转换Stytch OTP的cURL请求
解答
首先你不能直接把这段带-u 'MY-SECRET-YO'鉴权参数的请求直接写在React Native客户端代码里,有两个致命问题:
- 该参数是Stytch的服务端秘钥,客户端属于公开可反编译的环境,硬编码秘钥会直接导致你的Stytch账号被盗用,产生资损
- Stytch的服务端API默认禁止跨域客户端直接调用,直接请求会触发CORS拦截,根本无法正常返回结果
正确的实现方式有两种,按需选择即可:
方案1:使用Stytch官方React Native SDK(推荐,无需自建后端)
直接使用官方维护的客户端SDK,走公开客户端鉴权流程,不需要暴露服务端秘钥,是官方推荐的客户端接入方式:
- 先安装SDK依赖
npm install @stytch/react-native # 或者yarn add @stytch/react-native - 在应用入口初始化SDK,使用你项目的公开
public_token(注意是公开客户端令牌,不是服务端秘钥)import { StytchProvider, StytchClient } from '@stytch/react-native'; const stytchClient = new StytchClient('public-token-你的项目公开令牌'); export default function App() { return ( <StytchProvider stytch={stytchClient}> {/* 你的应用根组件 */} </StytchProvider> ) } - 在发送验证码的页面直接调用SDK提供的发送短信OTP方法即可
const handleSendOtp = async (phoneNumber) => { try { // phoneNumber必须是E.164格式,例如+8613xxxxxxxxx const resp = await stytchClient.otps.sms.send({ phone_number: phoneNumber }) // 发送成功,跳转到验证码输入页 console.log('OTP发送成功', resp) } catch (err) { console.error('发送失败', err) } }
后续验证码校验、会话管理SDK都有封装好的方法,直接调用即可,不需要自己处理鉴权逻辑。
方案2:自建后端代理接口
如果你不想用官方SDK,需要自己搭一层后端服务做请求代理,所有带服务端秘钥的请求都在后端完成:
- React Native客户端只负责把用户输入的手机号传给你自己的后端接口,不要带任何Stytch秘钥
// RN客户端请求示例 const sendOtp = async (phoneNumber) => { const resp = await fetch('https://你的业务域名/api/auth/send-sms-otp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone_number: phoneNumber }) }) const data = await resp.json() if (!resp.ok) throw new Error(data.message || '发送失败') return data } - 你的后端收到请求后,校验参数合法性,再构造带Basic Auth鉴权的请求转发给Stytch接口,以Node.js Express服务为例:
const express = require('express') const axios = require('axios') const app = express() app.use(express.json()) // 从环境变量读取Stytch凭证,绝对不要硬编码在代码里 const STYTCH_PROJECT_ID = process.env.STYTCH_PROJECT_ID const STYTCH_SECRET = process.env.STYTCH_SECRET app.post('/api/auth/send-sms-otp', async (req, res) => { const { phone_number } = req.body // 先校验手机号格式,必须符合E.164规范 if (!/^\+[1-9]\d{1,14}$/.test(phone_number || '')) { return res.status(400).json({ message: '手机号格式错误' }) } try { // 对应原cURL的-u鉴权参数:Basic Auth的用户名为项目ID,密码为服务端秘钥 const stytchResp = await axios.post( 'https://test.stytch.com/v1/otps/sms/send', { phone_number }, { auth: { username: STYTCH_PROJECT_ID, password: STYTCH_SECRET }, headers: { 'Content-Type': 'application/json' } } ) // 仅返回必要字段给客户端,不要透传Stytch返回的全量敏感数据 return res.json({ success: true, request_id: stytchResp.data.request_id }) } catch (err) { console.error('调用Stytch失败', err.response?.data || err.message) return res.status(500).json({ message: '验证码发送失败,请稍后重试' }) } }) app.listen(3000)
后续的OTP校验逻辑同理:客户端把用户输入的验证码传给后端,后端调用Stytch的校验接口,验证通过后给客户端下发你自己业务的登录凭证即可。
补充说明:你提供的cURL示例里
-u 'MY-SECRET-YO'是简化写法,实际Stytch的Basic Auth要求传入项目ID:秘钥拼接后的凭证,单独传秘钥会报鉴权失败。
内容的提问来源于stack exchange,提问作者akore128
相关产品推荐
相关产品推荐

