React Native Android端WebSocket连接报401未授权错误咨询
问题根因
出现双端鉴权表现不一致的核心原因是React Native在两个平台的WebSocket底层实现,对同域认证凭据的默认携带逻辑存在差异:
- iOS端WebSocket底层会默认自动携带同域名下HTTPS请求已存储的Cookie、会话认证凭证,你之前通过HTTPS接口完成身份认证后存储的凭据,会在发起wss握手请求时自动附加,服务端校验通过就能正常建立连接。
- Android端React Native的WebSocket底层基于OkHttp实现,默认配置下不会自动同步携带常规HTTPS请求栈存储的同域认证凭据,虽然你已经在同域名的HTTPS接口完成了登录认证,但发起wss握手请求时没有携带对应的认证信息,服务端收到无凭据的握手请求直接返回401 Unauthorized,最终抛出「Expected HTTP 101 response but was '401 Unauthorized'」错误。
公开测试地址wss://echo.websocket.events/.ws不需要任何身份认证即可建立连接,所以双端都能正常连通,和平台配置无关。
解决方案
不需要修改Android系统层面的配置,优先选择跨平台兼容的实现方式即可:
- 方案1(推荐):显式在WebSocket初始化时传入认证凭据
不要依赖平台默认的自动携带凭据逻辑,直接从本地存储(AsyncStorage、MMKV等)取出之前认证获得的token、会话标识,在初始化WebSocket时通过请求头显式传递,该方式双端通用,不会因为React Native版本升级、底层实现变动出现兼容问题。示例代码:useEffect(() => { // 替换为你本地存储的实际认证凭据 const authValue = "从本地存储读取的认证凭证值" const ws = new WebSocket( `wss://${DOMAIN}/api/stream/all`, [], // 无自定义子协议时传空数组即可 { headers: { // 根据服务端鉴权规则选择对应的头字段: // Cookie鉴权模式使用下面这行 'Cookie': `session_id=${authValue}`, // Token鉴权模式使用下面这行 // 'Authorization': `Bearer ${authValue}` } } ) ws.onopen = () => { console.log('websocket open') } ws.onerror = e => { console.log('error', e) } }, []) - 方案2:修改Android端原生配置开启自动携带Cookie
如果你一定要使用自动携带同域Cookie的逻辑,才需要修改Android端原生代码:找到项目路径下android/app/src/main/java/[你的项目包名]/MainApplication.java文件,在React Native网络栈初始化配置中,给WebSocket依赖的OkHttp客户端添加持久化CookieJar配置,对接系统Cookie管理器,配置完成后同域wss请求就会自动携带已存储的HTTPS认证Cookie。该配置仅对Android生效,iOS端默认已支持该能力无需修改。
注意:跨平台开发场景下,显式传递认证参数的方式兼容性远高于依赖平台默认行为,优先选择第一种方案。
内容的提问来源于stack exchange,提问作者Jamena McInteer
相关产品推荐
相关产品推荐

