如何处理 Flutter 上的 Firebase 身份验证异常

riz*_*izu 33 firebase firebase-authentication flutter

请问有人知道如何在flutter上捕获firebase Auth异常并显示它们吗?

注意:我对控制台不感兴趣 (catcherror((e) print(e))

我需要一些更有效的东西,例如“用户不存在”这样我就可以将它传递给一个字符串并显示它。

几个月来一直在处理这个问题。

提前致谢。

我试过用 // errorMessage=e.toString(); 替换 print(e); 然后将其传递给一个函数,所有的努力都是徒劳的。

    FirebaseAuth.instance
              .signInWithEmailAndPassword(email: emailController.text, password: passwordController.text)
              .then((FirebaseUser user) {
                _isInAsyncCall=false;
            Navigator.of(context).pushReplacementNamed("/TheNextPage");

          }).catchError((e) {
           // errorMessage=e.toString();
            print(e);
            _showDialog(errorMessage);

            //exceptionNotice();
            //print(e);
Run Code Online (Sandbox Code Playgroud)

我希望能够提取异常消息并将异常消息传递给一个对话框,然后我可以向用户显示该对话框。

小智 35

我只是为自己编写了一种无需平台相关代码即可执行此操作的方法:

这是可能的,因为 .signInWithEmailAndPassword 正确抛出带有定义代码的错误,我们可以抓住这些代码来识别错误并以应该处理的方式处理事情。

如果发生任何错误,以下示例将创建一个新的 Future.error,然后配置一个 Bloc 将该数据铲到 Widget。

Future<String> signIn(String email, String password) async {
  FirebaseUser user;
  String errorMessage;

  try {
    AuthResult result = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
    user = result.user;
  } catch (error) {
    switch (error.code) {
      case "ERROR_INVALID_EMAIL":
        errorMessage = "Your email address appears to be malformed.";
        break;
      case "ERROR_WRONG_PASSWORD":
        errorMessage = "Your password is wrong.";
        break;
      case "ERROR_USER_NOT_FOUND":
        errorMessage = "User with this email doesn't exist.";
        break;
      case "ERROR_USER_DISABLED":
        errorMessage = "User with this email has been disabled.";
        break;
      case "ERROR_TOO_MANY_REQUESTS":
        errorMessage = "Too many requests. Try again later.";
        break;
      case "ERROR_OPERATION_NOT_ALLOWED":
        errorMessage = "Signing in with Email and Password is not enabled.";
        break;
      default:
        errorMessage = "An undefined Error happened.";
    }
  }

  if (errorMessage != null) {
    return Future.error(errorMessage);
  }

  return user.uid;
}
Run Code Online (Sandbox Code Playgroud)

  • 我在这个答案中看到的唯一问题是 catch 中的“错误”并不总是包含“代码”,这意味着您的代码将因“Uncaught TypeError: e.get$code is not a functionError: TypeError: e. get$code 不是一个函数”因此您必须使用显式捕获,例如:“on PlatformException catch(e)”,然后您将确定它确实包含可以使用此答案中的开关处理的代码。附加说明:您还需要包含“import 'package:flutter/services.dart' show PlatformException;” 在您的进口中。 (4认同)
  • 以下是有效的错误代码列表:https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/signInWithEmailAndPassword.html (2认同)

Cor*_*yer 33

新答案 (18/09/2020)

如果您正在使用firebase_auth: ^0.18.0,错误代码已更改!

例如:ERROR_USER_NOT_FOUND现在user-not-found

我找不到任何关于它的文档,所以我进入了源代码并阅读了每个错误代码的注释。(firebase_auth.dart)

我不会在我的应用程序中使用所有错误代码(例如验证、密码重置...),但您会在此代码片段中找到最常见的错误代码:

(它处理旧的和新的错误代码)

String getMessageFromErrorCode() {
    switch (this.errorCode) {
      case "ERROR_EMAIL_ALREADY_IN_USE":
      case "account-exists-with-different-credential":
      case "email-already-in-use":
        return "Email already used. Go to login page.";
        break;
      case "ERROR_WRONG_PASSWORD":
      case "wrong-password":
        return "Wrong email/password combination.";
        break;
      case "ERROR_USER_NOT_FOUND":
      case "user-not-found":
        return "No user found with this email.";
        break;
      case "ERROR_USER_DISABLED":
      case "user-disabled":
        return "User disabled.";
        break;
      case "ERROR_TOO_MANY_REQUESTS":
      case "operation-not-allowed":
        return "Too many requests to log into this account.";
        break;
      case "ERROR_OPERATION_NOT_ALLOWED":
      case "operation-not-allowed":
        return "Server error, please try again later.";
        break;
      case "ERROR_INVALID_EMAIL":
      case "invalid-email":
        return "Email address is invalid.";
        break;
      default:
        return "Login failed. Please try again.";
        break;
    }
  }
Run Code Online (Sandbox Code Playgroud)


Swi*_*ter 19

(21/02/20) 编辑:这个答案很旧,其他答案包含跨平台解决方案,所以你应该先看看他们的解决方案并将其视为后备解决方案。

firebase auth 插件还没有真正的跨平台错误代码系统,因此您必须独立处理 android 和 ios 的错误。

我目前正在使用这个 github 问题的临时修复:#20223

请注意,因为它是临时修复,不要指望它作为永久解决方案是完全可靠的。

enum authProblems { UserNotFound, PasswordNotValid, NetworkError }

try {
  FirebaseUser user = await FirebaseAuth.instance.signInWithEmailAndPassword(
      email: email,
      password: password,
  );
} catch (e) {
  authProblems errorType;
  if (Platform.isAndroid) {
    switch (e.message) {
      case 'There is no user record corresponding to this identifier. The user may have been deleted.':
        errorType = authProblems.UserNotFound;
        break;
      case 'The password is invalid or the user does not have a password.':
        errorType = authProblems.PasswordNotValid;
        break;
      case 'A network error (such as timeout, interrupted connection or unreachable host) has occurred.':
        errorType = authProblems.NetworkError;
        break;
      // ...
      default:
        print('Case ${e.message} is not yet implemented');
    }
  } else if (Platform.isIOS) {
    switch (e.code) {
      case 'Error 17011':
        errorType = authProblems.UserNotFound;
        break;
      case 'Error 17009':
        errorType = authProblems.PasswordNotValid;
        break;
      case 'Error 17020':
        errorType = authProblems.NetworkError;
        break;
      // ...
      default:
        print('Case ${e.message} is not yet implemented');
    }
  }
  print('The error is $errorType');
}
Run Code Online (Sandbox Code Playgroud)


小智 8

我使用版本的异常代码管理 firebase auth 异常

firebase_auth: ^3.3.6
firebase_core: ^1.12.0
Run Code Online (Sandbox Code Playgroud)

这是对我有用的代码:

Future<void> loginWithEmailAndPassword({
required String email,
required String password,
}) async {
try {
  await _firebaseAuth.signInWithEmailAndPassword(
      email: email, password: password);
} on firebase_auth.FirebaseAuthException catch (e) {
  switch (e.code) {
    case "invalid-email":
      //Thrown if the email address is not valid.
      throw InvalidEmailException();
    case "user-disabled":
      //Thrown if the user corresponding to the given email has been disabled.
      throw UserDisabledException();
    case "user-not-found":
      //Thrown if there is no user corresponding to the given email.
      throw UserNotFoundException();
    case "wrong-password":
      throw PasswordExceptions();
    //Thrown if the password is invalid for the given email, or the account corresponding to the email does not have a password set.
    default:
      throw UncknownAuthException();
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

我创建了异常来控制稍后在 UI 中显示的消息,如下所示:

class AuthenticationException implements Exception {}
class InvalidEmailException extends AuthenticationException {}
class PasswordExceptions extends AuthenticationException {}
class UserNotFoundException extends AuthenticationException {}
class UserDisabledException extends AuthenticationException {}
class UncknownAuthException extends AuthenticationException {}
Run Code Online (Sandbox Code Playgroud)

希望它可以帮助那些在处理身份验证异常时遇到问题的人!


小智 7

可以使用 FirebaseAuthException 类处理异常。

以下是使用电子邮件和密码登录的代码:

void loginUser(String email, String password) async {
    try {
      await _auth.signInWithEmailAndPassword(email: email, password:password);
    } on FirebaseAuthException catch (e) {
      // Your logic for Firebase related exceptions
    } catch (e) {
    // your logic for other exceptions!
}
Run Code Online (Sandbox Code Playgroud)

您可以使用自己的逻辑来处理错误,例如显示警报对话框等。创建用户也可以这样做。


小智 6

在 Auth 类中有这个功能:

Future signUpWithEmailAndPassword(String email, String password) async {
    try {
      AuthResult result = await _auth.createUserWithEmailAndPassword(
        email: email,
        password: password,
      );
      FirebaseUser user = result.user;
      return user;
    } catch (e) {
      return e;
    }
  }
Run Code Online (Sandbox Code Playgroud)

上面的 catch 错误返回了 PlatformException 的 runTimeType,flutter 中的 PlatformException 在这里检查3 个属性!


在您的 Dart 文件中,在按钮侦听器上实现此功能:

String error = "";

dynamic result = await _auth.signUpWithEmailAndPassword(email, password);

if (result.runtimeType == PlatformException) {
    if (result.message != null) {
        setState(() {
            error = result.message;
        });
    } else {
        setState(() {
            error = "Unknown Error";
        });
    }
}
Run Code Online (Sandbox Code Playgroud)


Quw*_*sim 6

所以我今天遇到了这个问题,我决定使用字符串操作,而不是硬编码要显示的错误消息,并设法获取该消息。

目标是获取消息( 后的所有内容])。示例:获取此=>密码应至少包含6个字符来自此=> [firebase_auth/weak-password]密码应至少包含6个字符

因此,使用 try-catch 中的异常,我首先将其转换为字符串,然后将前 14 个字符(从 '[' 到 '/')替换为空,所以我留下了弱密码] 密码至少应该是6 个字符

然后使用 ']' 模式的 split 函数在剩余字符串中搜索 ']' 符号,并以 ']' 符号的索引为基准将整个字符串分成两部分。这将返回一个包含两个字符串的列表;'弱密码''密码应至少为 6 个字符'。使用索引 1 获取第二个字符串,即错误消息。

e.toString().replaceRange(0, 14, '').split(']')[1]
Run Code Online (Sandbox Code Playgroud)


gal*_*lki 5

扩展已接受的答案,我认为值得一提的是:

  1. firebase_auth插件有AuthException
  2. 正如这篇Github 问题帖子中所指出的,您可以在 Android 和 iOS 上使用相同的错误代码。
  3. 如果您在非 UI 层中有此代码,则可以使用rethrow或更好地抛出您自己的格式化异常并在 UI 级别捕获它们(您将确切知道将获得的错误类型)。

try {
  AuthResult authResult = await FirebaseAuth.instance.signInWithCredential(credential);
  // Your auth logic ...
} on AuthException catch (e) {
  print('''
    caught firebase auth exception\n
    ${e.code}\n
    ${e.message}
  ''');

  var message = 'Oops!'; // Default message
  switch (e.code) {
    case 'ERROR_WRONG_PASSWORD':
      message = 'The password you entered is totally wrong!';
      break;
    // More custom messages ...
  }
  throw Exception(message); // Or extend this with a custom exception class
} catch (e) {
  print('''
    caught exception\n
    $e
  ''');
  rethrow;
}
Run Code Online (Sandbox Code Playgroud)