firebase - 使用 Firebase 身份验证和 Rest Api 让用户永久登录 Flutter
问题描述
我正在为我的应用程序使用 firebase 电子邮件/密码身份验证并使用共享首选项存储令牌。我想在令牌过期之前刷新令牌,以便在用户输入凭据后保持用户永久登录。这是我的代码
class Auth with ChangeNotifier{
String _token;
DateTime _expiryDate;
String _userId;
Timer _authTimer;
bool get isAuth{
return token!=null;
}
String get token{
if(_expiryDate!=null&&_expiryDate.isAfter(DateTime.now())&& _token!=null){
return _token;
}
return null;
}
String get userId {
return _userId;
}
Future<void> _authenticate(String email, String password, String urlSegment ) async {
final url='https://identitytoolkit.googleapis.com/v1/$urlSegment? key';
try{
final response= await http.post(url, body: json.encode({
'email': email,
'password': password,
'returnSecureToken': true,
},
),
);
final responseData= json.decode(response.body);
if(responseData['error']!=null){
throw HttpException(responseData['error']['message']);
}
_token= responseData['idToken'];
_userId=responseData['localId'];
_expiryDate=DateTime.now().add(Duration
(seconds: int.parse(
responseData['expiresIn'])
)
);
_autoLogout();
notifyListeners();
final prefs=await SharedPreferences.getInstance();
final userData= json.encode({
'token': _token,
'userId': _userId,
'expiryDate': _expiryDate.toIso8601String(),
});
prefs.setString('userData', userData);
} catch (error){
throw(error);
}
}
Future<void> signup(String email, String password) async{
return _authenticate(email, password, 'accounts:signUp');
}
Future<void> login(String email,String password) async{
return _authenticate(email, password, 'accounts:signInWithPassword');
}
Future<bool> tryAutoLogin() async{
final prefs= await SharedPreferences.getInstance();
if(!prefs.containsKey('userData')){
return false;
}
final extractedUserData= json.decode(prefs.getString('userData')) as Map<String, Object>;
final expiryDate= DateTime.parse(extractedUserData['expiryDate']);
if(expiryDate.isBefore(DateTime.now()))
{
return false;
}
_token=extractedUserData['token'];
_userId=extractedUserData['userId'];
_expiryDate=expiryDate;
notifyListeners();
_autoLogout();
return true;
}
Future<void> logout() async{
_token=null;
_userId=null;
_expiryDate=null;
if(_authTimer!=null){
_authTimer.cancel();
_authTimer=null;
}
notifyListeners();
final prefs= await SharedPreferences.getInstance();
prefs.remove('userData');
}
void _autoLogout(){
if(_authTimer!=null){
_authTimer.cancel();
}
final timeToExpiry= _expiryDate.difference(DateTime.now()).inSeconds;
_authTimer= Timer(Duration(seconds: timeToExpiry), logout);
}
}
我想使用这种方法,因为我在整个代码中使用令牌进行身份验证。请提出任何实现刷新令牌的方法,以便即使在一小时后也能保持登录状态。
解决方案
推荐阅读
- webpack - 使用变量时导入('my-module')不起作用
- flutter - 颤振剪裁半径
- python - 在Django中获取上传的pdf文件的JSON
- php - 如何处理 GuzzleHttp 错误
- pygame - MOUSEBUTTONUP 与 mouse.get_pressed()
- c++ - 关于二进制转换的 C++ 代码到 R 代码
- javascript - 在 React 中为数组列表项添加空间
- reactjs - 更漂亮的错误:ENOENT:没有这样的文件或目录
- screensharing - 反应原生应用程序可以使用 Amazon Chime 屏幕共享功能吗?
- node.js - node.JS / Django - 配置 Apache / NGINX 从位置运行