React Native使用fetch发送http登陆验证请求失败:无法读取set-cookie并显示network request failed


发布者 ourjs  发布时间 1732592783263
关键字 java  react hooks 

React Native使用fetch发送http登陆验证请求失败:无法读取set-cookie头并显示network request failed

最近某个应用需要通过调用远程网站的登陆接口,登陆后调用其它API获取用户注册信息。

中间遇到两个坑。

Fetch不允许访问 Set-Cookie 这个 header

React Native 的网络层(基于 RCTNetworking 或底层的 OkHttp、NSURLSession 等)默认不暴露 Set-Cookie 给 JavaScript 层。这是出于安全考虑。对于原生Android应用也通常有同样的限制。

此时可在fetch或 XmlHttpRequest 中配置 credentials: 'include', 允许附加Cookie等信息。此时 react-native 会自动将服务器端写入的session类cookie回传给服务器。react-native只需要完成登陆过程即可。

也可以使用类似json web token的方法,将 sessionid 在服务器端放到响应json中。 如返回:

{
  jwt: {
    token: 'TOEKN_STRING'
  }
}

这样对web服务的改动非常小。后端不需要改变原有的 session 权限管理策略,如 redis 存储等。

    const res = await fetch(url, {
        method: 'GET',
        headers: { 
            'Cookie': 'sessionid=' + token
         },
        credentials: 'include'
    })

第二种方法就是采用jwt标准,在后续请求加上 authorization: Bearn TOEKN_STRING 这样的 header。

然后修改网站的权限验证机制,添加一个以 authorization 鉴权的中间件。这样的改动会略复杂一些。

Fetch不允许访问http请求

我们调试的请求类似 http://192.168.0.101/api/user/login

在虚拟机中是可以调用正常的,但在手机上测试,会一直显示 network request failed 异常。

从 Android 9(API 级别 28)开始,默认情况下,Android 应用是不允许使用明文网络流量的。这意味着,如果你的应用尝试通过 HTTP 而非 HTTPS 发送或接收数据,应用将会失败。

相关讨论如下:

https://github.com/facebook/react-native/issues/24627 https://github.com/facebook/react-native/issues/32931

我们可以配置 release 的 AndroidManifest.xml 允许明文流量: android:usesCleartextTraffic="true" 即可

AwesomeProject\android\app\src\main\AndroidManifest.xml

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme"
      android:usesCleartextTraffic="true"
      android:supportsRtl="true">
      <activity