如何在react-native-webview请求头中传递JWT令牌访问受保护网页
react-native-webview 传递JWT令牌加载受保护网页失效修复
你写的代码存在两个直接问题,同时受react-native-webview本身的特性限制,按下面步骤排查修复即可:
- 首先是令牌格式错误:标准
Authorization请求头的格式为Bearer <JWT令牌>,Bearer和令牌字符串之间必须有一个半角空格,你当前写法拼接后是BearereyJ0eX...........,服务端无法正确识别令牌前缀,会直接返回未授权。 - 其次是组件默认行为限制:写在
source.headers里的自定义请求头,只会在WebView首次加载主页面时携带,页面内加载的CSS、JS、接口请求、路由跳转等后续请求,都不会自动带上这个头,只要受保护站点对这些子资源做了权限校验,就会出现加载失败、白屏、跳登录页的问题。
基础修复(仅需校验主页面权限场景)
如果你的站点只对首屏页面请求做JWT校验,补上Bearer后面的空格即可正常使用:
<WebView source={{ uri: '替换为你的目标网站地址', headers: { Authorization: 'Bearer eyJ0eX...........', // 注意Bearer后保留半角空格 }, }} />
全场景修复(子资源/跳转都需要携带令牌场景)
如果改完格式还是加载失败,就需要拦截WebView内的所有请求,手动给所有同域请求注入JWT头,注意安卓端需要将react-native-webview版本升级到11.0.0以上才支持完整的拦截能力:
import React, { useRef } from 'react'; import { Platform } from 'react-native'; import { WebView } from 'react-native-webview'; const ProtectedWebView = () => { const webViewRef = useRef(null); // 实际使用时替换为动态获取的JWT令牌,不要硬编码 const JWT_TOKEN = 'eyJ0eX...........'; const TARGET_ORIGIN = '替换为你的目标网站根地址'; const handleRequestIntercept = (request) => { // 只拦截目标站点下的请求,避免影响第三方资源加载 if (!request.url.startsWith(TARGET_ORIGIN)) return true; // 安卓端通过注入JS重写fetch和XMLHttpRequest,自动给所有请求加头 if (Platform.OS === 'android') { const injectAuthScript = ` // 重写fetch const originFetch = window.fetch; window.fetch = (resource, init = {}) => { init.headers = { ...init.headers, Authorization: 'Bearer ${JWT_TOKEN}' }; return originFetch(resource, init); }; // 重写XMLHttpRequest const originXhrOpen = XMLHttpRequest.prototype.open; const originXhrSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function(method, url) { this._reqUrl = url; return originXhrOpen.apply(this, arguments); }; XMLHttpRequest.prototype.send = function(body) { if (this._reqUrl?.startsWith('${TARGET_ORIGIN}')) { this.setRequestHeader('Authorization', 'Bearer ${JWT_TOKEN}'); } return originXhrSend.call(this, body); }; true; `; webViewRef.current?.injectJavaScript(injectAuthScript); return true; } // iOS端直接在拦截回调里返回带自定义头的请求 return { ...request, headers: { ...request.headers, Authorization: `Bearer ${JWT_TOKEN}` } }; }; return ( <WebView ref={webViewRef} source={{ uri: TARGET_ORIGIN, headers: { Authorization: `Bearer ${JWT_TOKEN}` } }} onShouldStartLoadWithRequest={handleRequestIntercept} sharedCookiesEnabled={true} javaScriptEnabled={true} /> ); }; export default ProtectedWebView;
额外注意事项
- 如果目标站点开启了严格CORS校验,前端注入请求头的方式可能被跨域策略拦截,这种情况需要服务端配合配置跨域规则,或者由服务端做代理转发。
- 部分深度定制的安卓ROM会篡改WebView默认请求头,如果遇到个别机型始终带不上头,可以让服务端兼容读取自定义头比如
X-Authorization里的令牌,前端把令牌同时放到这个自定义头里做兼容。
内容的提问来源于stack exchange,提问作者Anand Lamani
相关产品推荐
相关产品推荐

