• 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

    Future> _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>{
              '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;
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    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,自动登录成功
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

      home: auth.isAuth
          ? ProductsOverviewScreen()
          : FutureBuilder(
              future: auth.tryAutoLogin(),
              builder: (ctx, authResultSnapShot) =>
                  authResultSnapShot.connectionState ==
                          ConnectionState.waiting
                      ? SplashScreen()
                      : AuthScreen(),
            ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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();
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    增加Linux用户
    低代码:API 开发的启动板
    Euler Integration
    【Leetcode】滑动窗口合集
    图解来啦!机器学习工业部署最佳实践!10分钟上手机器学习部署与大规模扩展 ⛵
    后端接口返回常见的状态码
    【Unity3D】顶点和片段着色器
    如何在PS(Adobe Photoshop)安装Portraiture3插件教程
    LLM(大语言模型)「Agent」开发教程-LangChain(三)
    计算机网络相关硬件介绍
  • 原文地址:https://blog.csdn.net/ftell/article/details/126909428