在不使用 Firebase 的情况下使用电子邮件和密码进行 Flutter 身份验证

Posted

技术标签:

【中文标题】在不使用 Firebase 的情况下使用电子邮件和密码进行 Flutter 身份验证【英文标题】:Flutter authentication with email and password without using Firebase 【发布时间】:2021-09-09 18:32:49 【问题描述】:

是否可以在不使用 firebase 的情况下通过电子邮件和密码实现身份验证?我在 *** 和互联网上进行了一般搜索,但没有发现任何相关信息。 我正在创建一个简单的身份验证类,这就是我目前所做的:

class User 
  bool isAuthenticated = false;
  late String userid;
  late String username;
  late String email;
  late DateTime expireDate; // this variable is used to make the user re-authenticate when today is expireDate

  User(bool isAuthenticated, String userid, String username, String email) 
    this.isAuthenticated = isAuthenticated;
    this.userid = userid;
    this.username = username;
    this.email = email;
    this.expireDate = new DateTime.now().add(new Duration(days: 30));
  


class Authentication 
  Future<User> signin(String email, String password) 

  void signup(String username, String email, String password) 

编辑 #1:我知道如何设置基于 cookie/令牌的身份验证服务器我有关于该主题的自己的存储库:cookie authentication,token authentication,但我不知道如何在颤动中处理令牌/cookie .

【问题讨论】:

***.com/questions/57531535/… 解决了吗? @Muhtar no 在那个问题中解释了如何使用firebase实现google身份验证,我想在没有firebase的情况下进行电子邮件和密码身份验证。 【参考方案1】:

此答案基于#edit1。既然您提到您已经知道如何在服务器端设置令牌,那么您已经完成了一半。这是我所做的一些假设,您已经了解 js/php 并使用 JSON 输出,数据库已经有一个列和表来跟踪会话和 user_id。

既然您知道 Cookie 是如何构建的,这应该相对容易,因为我围绕类似的架构构建它。我们必须使用应用程序提供访问权限的本地内存。颤振中有两个包可以让你这样做,你可以使用任何一个:

shared_preferences package link flutter_secure_storage package link

主要区别在于,如果您想存储“令牌”或您想要安全的数据,您显然会使用 flutter_secure_storage。我将使用它作为代码示例。是的,即使应用程序关闭,数据也会保存。

设置令牌(颤振):

    设置用户类

在使用 firebase 时,我们通常认为 flutter_auth 附带的用户类是理所当然的,但这基本上是我们必须构建的。一个包含你想要存储的所有数据的用户类,然后是一个名为 authenticate 的函数。

 class AppUser
     final _storage = new FlutterSecureStorage();
     //below class is mentioned in the next part 
     AuthApi api = new AuthApi();

     //constructor 
     AppUser()
         //ur data; 
     ; 

     Future<bool> authenticate(email, password) async 
         //this is the api mentioned in next part 
         http.Response res = await api.login(email, password);
         Map<String, dynamic> jsonRes = jsonDecode(res.body);

         if (jsonRes["error"]) 
              return false;
         
         _setToken(jsonRes["token"]);
         _setUID(jsonRes["user-id"].toString());
         _setAuthState(true); 
         return true; 
     

     Future<void> _setToken(String val) async 
         //how to write to safe_storage 
         await _storage.write(key: 'token', value: val);
     
     Future<void> _setUID(String val) async 
         await _storage.write(key: 'user_id', value: val);
     

      //you can stream this or use it in a wrapper to help navigate 
      Future<bool> isAuthenticated() async 
         bool authState = await _getAuthState();
         return authState;
      

      Future<void> _getAuthState() async 
         //how to read from safe_storage u can use the same to read token later just replace 'state' with 'token'
         String myState = (await _storage.read(key: 'state')).toString();
         //returns boolean true or false 
         return myState.toLowerCase() == 'true';
       

      Future<void> _setAuthState(bool liveAuthState) async 
         await _storage.write(key: 'state', value: liveAuthState.toString());
      

 

并假设您要在按下按钮时进行身份验证,所以它看起来像

onPressed()
        AuthUser user = new AuthUser(); 
        if(user.authenticate(email, password))
            //if logged in. Prolly call Navigator.
        else
            //handle error
        

    设置 api 调用

好吧,这是调用 Node express API,json 输出看起来像

//if successful 
"status":200, "error": false, "token": "sha256token", "user-id": "uid"

我们需要创建一个类,该类将为我们提供进行此调用的输出,因此是 AuthApi 类

class AuthApi 
   //this is the login api and it returns the above JSON 
   Future<http.Response> login(String email, String password)
        return http.post(
           Uri.parse(ip + '/api/auth/login'),
           headers: <String, String>
           'Content-Type': 'application/json',
           ,
           body: jsonEncode(<String, String>
           "email": email,
           "password": password,
           ),
       );
  

感谢您澄清您需要什么,它有助于更​​好地回答。

【讨论】:

【参考方案2】:

您可以使用 Nodejs & express 创建自己的 API 和 MongoDB 或任何其他数据库来充当持久数据库。我附上了我的 github repo 链接,该链接具有在 mongodb 中设置电子邮件/密码身份验证所需的最少代码

Github 编辑:

我对会话几乎一无所知,但对于令牌,pub.dev 中有一些包可以让您解码令牌。 jwt-decoder。 您可以使用此包检查令牌的到期时间,并使用 secure_storage 存储它们

我查看了您的令牌身份验证存储库。我建议您在获得令牌时对其进行验证,而不是盲目地信任它们。

【讨论】:

这不是一个有效的答案我已经知道如何使用身份验证设置后端服务器我有自己的存储库:token authentication 和cookie authentication,我的问题是如何处理 cookie/tokens颤动。 @AndreaDattero 你应该首先在你的问题中提到它。【参考方案3】:

是的,完全可以在没有 Firebase 的情况下创建身份验证,但它变得更加困难,并且有多种解决方案。

firebase 提供什么:

    无停机时间的服务器空间 完整的 API 集,包括使用各种方法进行身份验证 强大的安全性(由 google 构建) 易于使用和设置,文档丰富

我提出这些的原因是因为对于一个相对较新的程序员来说,你要寻找的替代方案非常困难,并且感觉你一次要构建多个应用程序。这绝对是一个学习曲线。另外我假设你不只是想要本地身份验证,因为那有点毫无意义。

创建自己的后端涉及:

    设置服务器(通常是 ubuntu)(在 raspi 或主机上,如亚马逊、数字海洋等) 使用表设置数据库(mysql、sql、mongoDB) 创建通信 API(php、Node.js)

所以这是我建议进入后端开发的内容, 使用 LAMP 架构:Linux、Apache、MySQL、PHP

设置 Lamp 并不难,这是我关注的链接:

https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-16-04

在你设置好你的后端之后,你必须从 Flutter 创建 api 调用。 调用(如果你创建了一个人们可以登录的 auth.php)看起来像:

http://ip:8080/auth.php?email="example@gmail.com"&pass="123456"

我理解你为什么觉得你没有找到解决方案,我也在那里,但有很多,LAMP 是更容易的解决方案之一。如果您仍然感兴趣,我建议您查看系统设计课程。

【讨论】:

这不是一个有效的答案我已经知道如何使用身份验证设置后端服务器我有自己的存储库:[github.com/datteroandrea/jwtauth](token 身份验证)和 [github.com/datteroandrea/cookieauth](cookie 身份验证),我的问题是如何在flutter中处理cookie/tokens。 哦,如果你更具体一点,我可以回答得更好,我刚刚创建了一个带有会话的项目。如果您再次阅读您的问题,它没有提到它..我现在会添加它

以上是关于在不使用 Firebase 的情况下使用电子邮件和密码进行 Flutter 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何在不关闭当前 Firebase 会话的情况下创建用户身份验证 [重复]

如何在不使用 Firebase 身份验证的情况下保护 Firebase 存储? (下一个)

如何在不使用验证码验证器的情况下实现 Firebase 电话验证系统?

在不使用数据库触发器的情况下,无法使用 firebase 云功能更新 firebase 数据库

如何在不退出的情况下使用 Firebase API 创建新用户? [复制]

在不使用 Firebase 身份验证的情况下设置 Firestore 安全规则