闲置5分钟后,React Native-注销用户

时间:2018-11-14 10:27:23

标签: react-native

5分钟不活动后,我试图注销并使用户令牌无效。

当应用程序处于“活动”阶段时,我正在使用react-native-user-inactivity,并将timeForInactivity设置为5分钟。但是,当应用程序在后台运行时,它具有预期的行为,尤其是当我将其设置为5分钟时。

我用了1分钟进行测试,并且运行良好,它过去一分钟才用于调用API并使令牌正确失效。但是,当我将其增加到5分钟时,直到应用程序阶段变为“活动”状态时才触发。

在AppState更改事件上使用setTimeout 5分钟时,我有类似的行为。

我只在iOS上尝试过,但是在某处我读到在Android上设置超时超过2分钟会出现错误。正确吗?

使用户令牌无效的最佳方法是什么: 1.当应用程序在后台运行时 2.就在关闭应用程序之前?

3 个答案:

答案 0 :(得分:0)

在移至后台(AppState)时,您可以将时间戳记存储在AsyncStorage中(或其他可以保存的东西)。在移至前台时,请检查当前日期是否早于5分钟。如果> 5分钟,请注销。我认为您不需要为此提供图书馆。那是您要找的东西吗?

答案 1 :(得分:0)

您可以使用react-native包中的PanResponder

我已使用自定义导航器将Panhandler事件通过screenProps传递到所有屏幕。检查以下功能,您可能需要根据需要更改代码。这确实对我有用。

import React, { Component } from 'react';
import { Button, PanResponder, Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';

// NOTE: you probably want this to be more than 2 seconds?
let TIME_TO_WAIT_FOR_INACTIVITY_MS = 1000;

// NOTE: this is how often you check whether the inactivity threshold has passed
const INACTIVITY_CHECK_INTERVAL_MS = 1000;

const LOG_OUT_POP = 4 * 60 * 1000;
//240,000 sec, 4 min

const LOG_OUT_USER = 60 * 1000;
// 60,000 , 1 min

export default class App extends Component {
  state = {};
  _lastInteraction = new Date();
  _panResponder = {};
  _timeIntervalForLoggingOut;

  componentWillMount() {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: this.handleStartShouldSetPanResponder,
      onMoveShouldSetPanResponder: this.handleMoveShouldSetPanResponder,
      onStartShouldSetPanResponderCapture: () => false,
      onMoveShouldSetPanResponderCapture: () => false,
      onPanResponderTerminationRequest: () => true,
      onShouldBlockNativeResponder: () => false,
    });

    this._maybeStartWatchingForInactivity();
  }

  _maybeStartWatchingForInactivity = () => {
    if (this._inactivityTimer) {
      return;
    }
    /**
     * - Issue https://github.com/facebook/react-native/issues/12981
     * - to over the android performance issue of setTimeout, we have used setInterval and kept checking the time difference every secound.
     */
    this._inactivityTimer = setInterval(() => {
      if (LOG_OUT_POP <= TIME_TO_WAIT_FOR_INACTIVITY_MS) {
        // show Alert timer
        console.log('ALERT TIMER 4 Minutes');
        clearInterval(this._inactivityTimer);

        /* 
        * Start new timer for loggin out user
        * Dont' forget to all clearInterval
        */

        this.timeIntervalForLoggingOut = setInterval(() => {
          if (LOG_OUT_USER <= TIME_TO_WAIT_FOR_INACTIVITY_MS) {
            // show Alert timer
            console.log('LOG OUT USER');
            clearInterval(this._inactivityTimer);
            clearInterval(this._timeIntervalForLoggingOut);
            //
          } else {
            this._setIsInactive();
          }
        }, INACTIVITY_CHECK_INTERVAL_MS);

        /* */


        //
      } else {
        this._setIsInactive();
      }
    }, INACTIVITY_CHECK_INTERVAL_MS);
  };

  // NOTE: you almost certainly want to throttle this so it only fires
  // every second or so!
  _setIsActive = () => {
    // this._lastInteraction = new Date();
    console.log(TIME_TO_WAIT_FOR_INACTIVITY_MS);
    TIME_TO_WAIT_FOR_INACTIVITY_MS += 1000;
    if (this.state.timeWentInactive) {
      this.setState({ timeWentInactive: null });
    }
    this._maybeStartWatchingForInactivity();
  };

  _setIsInactive = () => {
    this.setState({ timeWentInactive: new Date() });
    clearInterval(this._inactivityTimer);
    this._inactivityTimer = null;
  };

  render() {
    return (
      <View
        style={styles.container}
        collapsable={false}
        {...this._panResponder.panHandlers}>
        <Text style={styles.paragraph}>
          Put your app here{' '}
          {this.state.timeWentInactive &&
            `(inactive at: ${this.state.timeWentInactive})`}
        </Text>

        <Button
          title="Here is a button for some reason"
          onPress={() => alert('hi')}
        />
      </View>
    );
  }

  handleStartShouldSetPanResponder = () => {
    this._setIsActive();
    return false;
  };

  handleMoveShouldSetPanResponder = () => {
    this._setIsActive();
    return false;
  };
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#34495e',
  },
});

参考:

  1. https://reactnavigation.org/docs/en/custom-navigators.html
  2. https://medium.com/@benjaminwfox/share-state-between-screens-with-custom-navigators-in-react-navigation-62a34e3c7f97
  3. The app is crashing when I navigate while going back using pop()

原文:https://snack.expo.io/SyGLEApZb

调整:https://snack.expo.io/@ashish9342/warn-about-inactivity

答案 2 :(得分:0)

试试这个

根据需要修改

import { useCallback, useEffect, useRef, useState } from 'react'
import { AppState } from 'react-native'
import { useLazyApiData, useStores } from '../../data/store'

const inactiveTimeInMinute = 10
const millisecToMins = 60000

export const InactivityHandler = (navigationReset: () => void): any => {
  const appState = useRef(AppState.currentState)
  const [appStateVisibl, setAppStateVisible] = useState(appState.current)
  console.log(appStateVisibl)

  const { inactiveTime, resetInactivityTimer, updateInactivityTime, logout } = useStores((store) => ({
    inactiveTime: store?.user?.inactiveTime,
    resetInactivityTimer: store?.user?.resetInactivityTimer,
    updateInactivityTime: store?.user?.updateInactivityTime,
    logout: store?.user?.session?.logout,
  }))

  const [logoutAPI, { state: logoutapistatehandler }] = useLazyApiData(logout)

  useEffect(() => {
    if (logoutapistatehandler === 'fulfilled' || logoutapistatehandler === 'rejected') {
      navigationReset()
    }
  })

  const onAppStateChange = useCallback(
    (nextAppState: any) => {
      if (appState.current.match(/inactive|background/)) {
        updateInactivityTime(Date.now())
      }
      if (appState.current.match(/inactive|background/) && nextAppState === 'active') {
        const differenceInElapsedTime = Date.now() - inactiveTime
        const backgroundElapsedTime = Math.floor(differenceInElapsedTime / millisecToMins)
        // var ELLAPSED_SECOND = (differenceInElapsedTime % 60000) / 1000 //For testing use second
        if (backgroundElapsedTime >= inactiveTimeInMinute) {
          logoutAPI()
        } else {
          resetInactivityTimer()
        }
      }
      appState.current = nextAppState
      setAppStateVisible(appState.current)
    },
    [inactiveTime, logoutAPI, resetInactivityTimer, updateInactivityTime],
  )

  useEffect(() => {
    AppState.addEventListener('change', onAppStateChange)
    return () => {
      AppState.removeEventListener('change', onAppStateChange)
    }
  }, [onAppStateChange])
}