Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep last web session active in react-native-webview?

I am working on one app, In which I need to keep users last web-session active in react-native-webview.

Here is a required work-flow.

  • My app is only have one WebView, Where there is fixed url is loading.

  • User will open app & login to that website.

  • When user will kill app & open it again, I need to keep that user logged in as he has already logged in last time.

Here is what i tried so far:

  • I did try with https://github.com/react-native-community/cookies. Till now I am only able to save cookies via below function :

// list cookies (IOS ONLY)

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

But as it's suggested, It'll only work in iOS. I am also not able to set that cookies in website that is opened in WebView to keep that session active.

  • Also used this one, https://gist.github.com/kanzitelli/e5d198e96f81b7a8263745043766127c

But I didn't found any success yet.

Any suggestion or solution will highly appreciated.

======= Update =======

For Android:

It is working by default, That means we only need to check this for iOS.

like image 690
Vishal Sharma Avatar asked May 28 '20 05:05

Vishal Sharma


1 Answers

actually this problem exist in react-native-webview

Cookies are lost on iOS after application closing

it should be resolve through native code. but today I made a solution and tested with PHP website

Full Code

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',
  },
});

Detail:

Step 1:

get cookies after login and save in AsyncStorage like this

onNavigationStateChange = (navState) => {
    this.currentUrl = navState.url;
  };
 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);
        }
      });
    }
  };

Step 2:

enable sharedCookiesEnabled props and get saved cookies in componentWillMount and make required webview header cookies formate by jsonCookiesToCookieString function and stop render webview by isReady props utils you get cookies

jsonCookiesToCookieString = (json) => {
    let cookiesString = '';
    for (let [key, value] of Object.entries(json)) {
      cookiesString += `${key}=${value.value}; `;
    }
    return cookiesString;
  };
provideMeSavedCookies = async () => {
    try {
      let value = await AsyncStorage.getItem('savedCookies');
      if (value !== null) {
        return Promise.resolve(JSON.parse(value));
      }
    } catch (error) {
      return {}
    }
  };
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});
      });
  }

Step 3:

pass cookiesString in Webview Header and write render function like this

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>
    );
  }
like image 133
Muhammad Numan Avatar answered Nov 04 '22 13:11

Muhammad Numan