Flutter: 自动登录

类似于 JavaScript 中的 localStorage API,Flutter 使用 shared_preferences 插件持久保存数据。

如果用户关闭 app, 再次打开时,自动通过 SharedPreferences 读取上次登录后保存的数据,如果认证 token 依然有效,则使用存储的数据重设相应的数据,从而跳过手动输入帐号密码进行登录这一步。

1. 修改 pubspec.yaml 并保存

增加 shared_preferences 这一项,版本一直在更新。 shared_preferences 网页:https://pub.dev/packages/shared_preferences , 不过 pub.dev经常打不开,原因不明。

dependencies:
  flutter:
    sdk: flutter
  provider: ^4.0.0
  intl: ^0.15.8
  http: ^0.12.0+2
  shared_preferences: ^0.5.3+1

2. 登录成功后,保存从服务器获取的认证相关数据

Future<void> _authenticate(
      String email, String password, String urlSegment) async {
    final url =
        'https://identitytoolkit.googleapis.com/v1/accounts:${urlSegment}?key=somekey_from_firebase_xyz';
    try {
      final response = await http.post(
        url,
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        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;
    }
  }

3. 自动登录函数 tryAutoLogin() 代码

Future<bool> tryAutoLogin() async {
    final prefs = await SharedPreferences.getInstance();
    if (!prefs.containsKey('userData')) {
      return false;  // 没有'userData'这一项,返回 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 过期,返回 false,自动登录失败
    }
    _token = extractedUserData['token'];
    _userId = extractedUserData['userId'];
    _expiryDate = expiryDate; 
    notifyListeners();
    _autoLogout();
    return true;  // 数据有效,返回 true,自动登录成功
  }

4. 在 main.dart 中调用自动登录函数

  home: auth.isAuth
      ? ProductsOverviewScreen()
      : FutureBuilder(
          future: auth.tryAutoLogin(),
          builder: (ctx, authResultSnapShot) =>
              authResultSnapShot.connectionState ==
                      ConnectionState.waiting
                  ? SplashScreen()
                  : AuthScreen(),
        ),

5. 在退出登录函数中增加清空数据这一步

退出登录时,步骤 2 中保存的数据要清除,有两种清除数据的方法:

  1. prefs.remove('userData'); 删除当前app 写入的 userData key value 对
  2. prefs.clear(); // 全部删除,因为也可能包括别的app的数据,所以不要随意使用。
  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');
    prefs.clear();
  }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值