我可以使用我的用户名和密码(硬编码)登录,但是,登录后我想从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中。因此,例如,在初始屏幕上,启动画面会给出条件,以检查是否通过使用呈现令牌
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)
})
})
}