如何保持用户登录(使用 AsyncStorage 存储 userId)

How to keep user logged in (store userId with AsyncStorage)

我可以使用我的用户名和密码(硬编码)登录,但是,登录后我想从 API 获取一些数据,这只有在我通过身份验证后才能完成。 那么,问题是如何让用户保持登录状态?

我不太擅长 React-Native,所以非常感谢任何帮助!

这是我的代码:

import React, { Component } from 'react';
import { Text, View, StyleSheet,AsyncStorage, FlatList, AppRegistry } from 'react-native';
import { ListItem } from 'react-native-elements';


export default class BMPServer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
       username: 'testuser', 
       password: 'mypasswordhere',
       signedIn: false,
      checkedSignIn: false 
      };


    this.getAllDocuments();

 }
getAllDocuments = () => {

  fetch('https://example.dk/rest/Login/Authenticate/?businessId=1&solutionId=1', {
            method: 'POST',
            headers: {
              Accept: 'application/json',
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              username : this.state.username,
              password : this.state.password,
            })
          }) 

        .then((response) => response.json())

      .then((responseDocs) => {

        console.log("YOU HAVE SUCCSFULLY LOGGED IN:", responseDocs) 

});}

假设您在成功验证后获得令牌。

    import { AsyncStorage } from 'react-native';

    fetch('https://example.dk/rest/Login/Authenticate/?businessId=1&solutionId=1', {
            method: 'POST',
            headers: {
              Accept: 'application/json',
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              username : this.state.username,
              password : this.state.password,
            })
          }) 

        .then((response) => AsyncStorage.setItem(LOGIN_TOKEN, response))

      .then((responseDocs) => {

        console.log("YOU HAVE SUCCSFULLY LOGGED IN:", responseDocs) 

     });}

所以,现在您已将令牌存储在异步存储中。因此,例如,在您的初始屏幕上,启动画面给出了一个条件来检查令牌是否通过使用

AsyncStorage.getItem(LOGIN_TOKEN);

React navigation 在 https://reactnavigation.org/docs/en/auth-flow.html

上有一个带有 Switch Navigator 的身份验证流程示例

基本上你有一个特殊的导航器用于在登录和未登录用户之间切换,因为 AsyncStorage 持续存在,所以应该没有问题。

这是代码,运行。这很简单:)

import React from 'react';
import {
  ActivityIndicator,
  AsyncStorage,
  Button,
  StatusBar,
  StyleSheet,
  View,
} from 'react-native';
import { createStackNavigator, createSwitchNavigator, createAppContainer } from 'react-navigation';

class SignInScreen extends React.Component {
  static navigationOptions = {
    title: 'Please sign in',
  };

  render() {
    return (
      <View style={styles.container}>
        <Button title="Sign in!" onPress={this._signInAsync} />
      </View>
    );
  }

  _signInAsync = async () => {
    await AsyncStorage.setItem('userToken', 'abc');
    this.props.navigation.navigate('App');
  };
}

class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome to the app!',
  };

  render() {
    return (
      <View style={styles.container}>
        <Button title="Show me more of the app" onPress={this._showMoreApp} />
        <Button title="Actually, sign me out :)" onPress={this._signOutAsync} />
      </View>
    );
  }

  _showMoreApp = () => {
    this.props.navigation.navigate('Other');
  };

  _signOutAsync = async () => {
    await AsyncStorage.clear();
    this.props.navigation.navigate('Auth');
  };
}

class OtherScreen extends React.Component {
  static navigationOptions = {
    title: 'Lots of features here',
  };

  render() {
    return (
      <View style={styles.container}>
        <Button title="I'm done, sign me out" onPress={this._signOutAsync} />
        <StatusBar barStyle="default" />
      </View>
    );
  }

  _signOutAsync = async () => {
    await AsyncStorage.clear();
    this.props.navigation.navigate('Auth');
  };
}

class AuthLoadingScreen extends React.Component {
  constructor() {
    super();
    this._bootstrapAsync();
  }

  // Fetch the token from storage then navigate to our appropriate place
  _bootstrapAsync = async () => {
    const userToken = await AsyncStorage.getItem('userToken');

    // This will switch to the App screen or Auth screen and this loading
    // screen will be unmounted and thrown away.
    this.props.navigation.navigate(userToken ? 'App' : 'Auth');
  };

  // Render any loading content that you like here
  render() {
    return (
      <View style={styles.container}>
        <ActivityIndicator />
        <StatusBar barStyle="default" />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const AppStack = createStackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = createStackNavigator({ SignIn: SignInScreen });

export default createAppContainer(createSwitchNavigator(
  {
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'AuthLoading',
  }
));

我找到了解决问题的方法。 Fetch() 会自动设置 cookie,但您必须在获取时包括:凭据:'include'。 不需要 AsyncStorage 或类似的东西,这只是浪费时间,不幸的是,即使在搜索这个问题一周后,我也无法在互联网上的任何地方找到解决方案,显然解决方案非常非常简单。

详情见下方代码:

getAllDocuments = () => {
    fetch('LOGIN_URL_HERE', {     //*HERE I AM AUTHENTICATING*
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'Connection': 'Keep-Alive',
      },
      body: JSON.stringify({
        username: 'myemail',
        password: 'mypassword'
      })
    })
      .then((response) => response.json())

      .then((res) => {

        console.log("This is the user:", res)

        fetch('DOCUMENTS_URL_HERE', {    //*HERE I AM FETCHING DOCUMENTS AFTER I HAVE SUCCESSFULLY AUTHENTICATED*
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
          },
          credentials: 'include',     //USE THIS TO SET COOKIES
          body: JSON.stringify({
            lastServerSyncDateAsLong: 0,
            inserted: {},
            edited: {},
            deleted: {}
          })
        })
     .then((res) => res.json())

          .then((ressDocs) => {
            console.log("THESE ARE ALL DOCUMENTS FETCHED FROM API:", ressDocs)
          })

      })

  }