【问题标题】:React Native - Webview set cookies policyReact Native - Webview 设置 cookie 策略
【发布时间】:2021-11-26 20:04:02
【问题描述】:

为了给您提供上下文,我们的应用是一个 react-native web wrapper(类似于 Cordova 或 ionic 所做的)。

用户打开应用后,应用会下载本地存储的 Web 包的更新版本,然后 WebView 组件将其作为源向用户展示应用。

这个 Web 应用程序的某些部分使用 Web 套接字,所以问题是考虑到它的大流量,套接字/交换服务有一堆节点/副本,为了保持连接活动,负载均衡器使用 Set -Cookie 标头,以确保客户端在每个请求中都转到正确的服务节点

所以,我们正在尝试的是:

  • 在 WebView 中启用 Set-Cookie 行为
  • 从 WebView 中发生的请求手动获取 Set-Cookie 响应标头

我们的 react-native 应用程序如下所示:

import React from 'react';
import {Platform, StyleSheet, View} from 'react-native';
import {WebView} from 'react-native-webview';

type WrapperProps = {
  path: string;
};

function Wrapper({path}: WrapperProps) {
  return (
    <View style={styles.container}>
      <WebView
        allowFileAccess
        allowUniversalAccessFromFileURLs
        allowingReadAccessToURL={path}
        javaScriptEnabled
        originWhitelist={['*']}
        sharedCookiesEnabled
        source={{
          uri:
            Platform.OS === 'ios'
              ? `file://${path}/index.html`
              : `${path}/index.html`,
        }}
        injectedJavaScript={`(function () {
          window.ReactNativeWebView.postMessage(JSON.stringify(document.coookie));
          var open = XMLHttpRequest.prototype.open;
          XMLHttpRequest.prototype.open = function (method, url) {
            this.addEventListener("load", function () {
              var responseHeaders = this.getAllResponseHeaders();
              var setCookies = this.getResponseHeader("Set-Cookie"); // always return null
              window.ReactNativeWebView.postMessage(JSON.stringify({ setCookies }));
              window.ReactNativeWebView.postMessage(
                JSON.stringify({ responseHeaders }) // return all headers except for Set-Cookie 
              );
            });
            open.apply(this, arguments);
          };
        })();
        `}
        onMessage={e => {
          console.log({onMessageEvent: e.nativeEvent.data});
        }}
        style={styles.webview}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  webview: {
    height: '100%',
    width: '100%',
  },
});

export default React.memo(Wrapper);

你知道如何解决这个问题吗?

P.S:我们已经阅读了How to set WKWebView cookie to accept Policy - 但它是为 swift 准备的。

【问题讨论】:

    标签: ios react-native cookies webview wkwebview


    【解决方案1】:

    我成功了

    在 WebView 中启用 Set-Cookie 行为

    通过使用socket.io-client 建立套接字连接,因此 WebView 中的 Web 套接字请求将已经在请求标头中包含 cookie(这将使连接保持活动状态)。

    考虑到react-native-webview 在iOS 上使用WKWebViewthere is no way to access cookies in response headers。但是,在这种特殊情况下,您可以从 Web 视图外部创建套接字连接,处理 cookie(似乎socket.io-client 已经这样做了),然后它们应该在 WebView 内的请求中可用。

    为了在你的 react-native 应用中设置 socket io,你需要

    • 安装socket.io-client@2.1.1(我尝试了不同的版本,但这是唯一可行的)
    • 赋值window.navigator.userAgent = 'react-native';(由于ES6模块被提升,这个赋值不能和react-native和socket io导入在同一个文件中完成)
    • 建立您的套接字连接。

    所以它应该是这样的:

    // userAgent.js
    window.navigator.userAgent = 'react-native';
    
    
    // Wrapper.tsx
    import React from 'react';
    import {Platform, StyleSheet, View} from 'react-native';
    import {WebView} from 'react-native-webview';
    // user agent MUST be imported before socket io
    import './userAgent';
    import io from 'socket.io-client';
    
    
    export const socket = io('https://your.host.com/', {
      path: '/path/to/socket.io/',
      jsonp: false,
    });
    
    
    type WrapperProps = {
      path: string;
    };
    
    function Wrapper({path}: WrapperProps) {
      return (
        <View style={styles.container}>
          <WebView
            allowFileAccess
            allowUniversalAccessFromFileURLs
            allowingReadAccessToURL={path}
            javaScriptEnabled
            originWhitelist={['*']}
            sharedCookiesEnabled
            source={{
              uri:
                Platform.OS === 'ios'
                  ? `file://${path}/index.html`
                  : `${path}/index.html`,
            }}
            style={styles.webview}
          />
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
      },
      webview: {
        height: '100%',
        width: '100%',
      },
    });
    
    export default React.memo(Wrapper);
    

    【讨论】:

      猜你喜欢
      • 2018-02-05
      • 2017-10-15
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 2018-01-27
      • 1970-01-01
      • 2012-08-06
      • 1970-01-01
      相关资源
      最近更新 更多