如何在 react-native-webview 中保持最后一个 Web 会话处于活动状态?

Sha*_*hal 8 authentication cookies session react-native react-native-webview

我正在开发一个应用程序,在该应用程序中,我需要让用户在react-native-webview.

这是一个必需的工作流程。

  • 我的应用程序只有一个 WebView,正在加载固定 url。

  • 用户将打开应用程序并登录该网站。

  • 当用户将终止应用程序并再次打开它时,我需要让该用户保持登录状态,因为他上次已经登录。

这是我到目前为止尝试过的:

// 列出 cookie(仅限 IOS)

CookieManager.getAll(useWebKit)
    .then((res) => {
        console.log('CookieManager.getAll from webkit-view =>', res);
    });
Run Code Online (Sandbox Code Playgroud)

但正如它所建议的那样,它只能在 iOS 中运行。我也无法在 WebView 中打开的网站中设置该 cookie 以保持该会话处于活动状态。

但我还没有发现任何成功。

任何建议或解决方案将不胜感激。

========更新======

对于安卓:

它默认工作,这意味着我们只需要为 iOS 进行检查。

Muh*_*man 6

实际上这个问题存在于 react-native-webview

应用程序关闭后,iOS 上的 Cookie 会丢失

它应该通过本机代码解决。但是今天我做了一个解决方案并用PHP网站进行了测试

完整代码

import React, {Component} from 'react';
import {StyleSheet, SafeAreaView} from 'react-native';
import {WebView} from 'react-native-webview';
import CookieManager from '@react-native-community/cookies';
import AsyncStorage from '@react-native-community/async-storage';

let domain="http://example.com";

export default class App extends Component {
  constructor(props) {
    super(props);
    this.currentUrl = '';
    this.myWebView = React.createRef();
    this.state = {
      isReady: false,
      cookiesString: '',
    };
  }

  jsonCookiesToCookieString = (json) => {
    let cookiesString = '';
    for (let [key, value] of Object.entries(json)) {
      cookiesString += `${key}=${value.value}; `;
    }
    return cookiesString;
  };

  componentWillMount() {
    this.provideMeSavedCookies()
      .then(async (savedCookies) => {
        let cookiesString = this.jsonCookiesToCookieString(savedCookies);
        const PHPSESSID = await AsyncStorage.getItem('PHPSESSID');
        if (PHPSESSID) {
          cookiesString += `PHPSESSID=${PHPSESSID};`;
        }
        this.setState({cookiesString, isReady: true});
      })
      .catch((e) => {
        this.setState({isReady: true});
      });
  }

  onLoadEnd = (syntheticEvent) => {
    let successUrl = `${domain}/report.php`;
    if (this.currentUrl === successUrl) {
      CookieManager.getAll(true).then((res) => {
        AsyncStorage.setItem('savedCookies', JSON.stringify(res));
        if (res.PHPSESSID) {
          AsyncStorage.setItem('PHPSESSID', res.PHPSESSID.value);
        }
      });
    }
  };
  onNavigationStateChange = (navState) => {
    this.currentUrl = navState.url;
  };


  provideMeSavedCookies = async () => {
    try {
      let value = await AsyncStorage.getItem('savedCookies');
      if (value !== null) {
        return Promise.resolve(JSON.parse(value));
      }
    } catch (error) {
      return {}
    }
  };

  render() {
    const {cookiesString, isReady} = this.state;
    if (!isReady) {
      return null;
    }
    return (
      <SafeAreaView style={styles.container}>
        <WebView
          ref={this.myWebView}
          source={{
            uri: `${domain}`,
            headers: {
              Cookie: cookiesString,
            },
          }}
          scalesPageToFit
          useWebKit
          onLoadEnd={this.onLoadEnd}
          onNavigationStateChange={this.onNavigationStateChange}
          sharedCookiesEnabled
          javaScriptEnabled={true}
          domStorageEnabled={true}
          style={styles.WebViewStyle}
        />
      </SafeAreaView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FFF',
  },
  WebViewStyle: {
    flex: 1,
    resizeMode: 'cover',
  },
});
Run Code Online (Sandbox Code Playgroud)

细节:

第1步:

登录后获取cookies并像这样保存在AsyncStorage中

onNavigationStateChange = (navState) => {
    this.currentUrl = navState.url;
  };
Run Code Online (Sandbox Code Playgroud)
 onLoadEnd = () => {
    let successUrl = `${domain}/report.php`;
    if (this.currentUrl === successUrl) {
      CookieManager.getAll(true).then((res) => {
        AsyncStorage.setItem('savedCookies', JSON.stringify(res));
        if (res.PHPSESSID) {
          AsyncStorage.setItem('PHPSESSID', res.PHPSESSID.value);
        }
      });
    }
  };
Run Code Online (Sandbox Code Playgroud)

第2步:

使 sharedCookiesEnabled道具和componentWillMount得到保存的cookies,并需要的WebView头饼干甲酸盐jsonCookiesToCookieString功能,并停止通过渲染的WebViewisReady道具utils的你的cookies

jsonCookiesToCookieString = (json) => {
    let cookiesString = '';
    for (let [key, value] of Object.entries(json)) {
      cookiesString += `${key}=${value.value}; `;
    }
    return cookiesString;
  };
Run Code Online (Sandbox Code Playgroud)
provideMeSavedCookies = async () => {
    try {
      let value = await AsyncStorage.getItem('savedCookies');
      if (value !== null) {
        return Promise.resolve(JSON.parse(value));
      }
    } catch (error) {
      return {}
    }
  };
Run Code Online (Sandbox Code Playgroud)
componentWillMount() {
    this.provideMeSavedCookies()
      .then(async (savedCookies) => {
        let cookiesString = this.jsonCookiesToCookieString(savedCookies);
        const PHPSESSID = await AsyncStorage.getItem('PHPSESSID');
        if (PHPSESSID) {
          cookiesString += `PHPSESSID=${PHPSESSID};`;
        }
        this.setState({cookiesString, isReady: true});
      })
      .catch((e) => {
        this.setState({isReady: true});
      });
  }
Run Code Online (Sandbox Code Playgroud)

第 3 步:

Webview Header 中传递 cookiesString并像这样编写渲染函数

render() {
    const {cookiesString, isReady} = this.state;
    if (!isReady) {
      return null;
    }
    return (
      <SafeAreaView style={styles.container}>
        <WebView
          ref={this.myWebView}
          source={{
            uri: `${domain}`,
            headers: {
              Cookie: cookiesString,
            },
          }}
          scalesPageToFit
          useWebKit
          onLoadEnd={this.onLoadEnd}
          onNavigationStateChange={this.onNavigationStateChange}
          sharedCookiesEnabled
          javaScriptEnabled={true}
          domStorageEnabled={true}
          style={styles.WebViewStyle}
        />
      </SafeAreaView>
    );
  }
Run Code Online (Sandbox Code Playgroud)

  • 注意:此解决方案不适用于仅 http 的 cookie(显然) (2认同)