플러터 시 Firebase Auth 예외 처리 방법
플러터 시 Firebase Auth 예외 처리 방법
플레어 시 파이어베이스 인증 예외를 포착하여 표시하는 방법을 아는 사람이 있습니까?
참고: 저는 콘솔에 관심이 없습니다(캐처 오류(e) 인쇄(e))
"사용자가 존재하지 않습니다."와 같이 더 효과적인 것이 필요합니다. 그러면 문자열로 전달하고 표시할 수 있습니다.
몇 달 동안 이 일을 처리했어요.
잘 부탁드립니다.
나는 print(e)를 // errorMessage=e.toString()으로 대체하려고 시도했지만, 그것을 함수에 전달하는 모든 노력이 헛수고였다.
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);
예외 메시지를 추출하여 사용자에게 표시할 수 있는 대화 상자에 예외 메시지를 전달할 수 있어야 합니다.
(21/02/20) 편집: 이 답변은 오래되었고 다른 답변에는 교차 플랫폼 솔루션이 포함되어 있으므로 먼저 해당 솔루션을 살펴보고 이를 폴백 솔루션으로 처리해야 합니다.
파이어베이스 인증 플러그인은 아직 제대로 된 크로스 플랫폼 오류 코드 시스템이 없기 때문에 안드로이드와 iOS의 오류를 독립적으로 처리해야 한다.
나는 현재 이 github 이슈의 임시 수정을 사용하고 있다:
수정 사항이므로 영구적인 해결책으로 완전히 신뢰할 수 있을 것으로 기대하지 마십시오.
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');
}
firebase_auth: ^0.18.0을 사용하는 경우 오류 코드가 변경되었습니다! 다음 답을 확인하세요.
플랫폼 종속 코드 없이 이 작업을 수행할 수 있는 방법을 코딩했습니다:
이는 .signInWithEmailAndPassword가 정의된 코드와 함께 오류를 올바르게 발생시켜 오류를 식별하고 처리해야 하는 방식으로 작업을 처리할 수 있기 때문에 가능합니다.
다음 예제에서는 오류가 발생할 경우 새로운 Future.error를 생성한 다음 해당 데이터를 위젯으로 이동하도록 블록을 구성합니다.
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;
}
수락된 답변을 확장하면서 다음과 같이 언급할 가치가 있다고 생각했습니다:
- 플러그인에 가 있습니다.
- 여기서 지적했듯이 안드로이드와 iOS에 동일한 오류 코드가 있을 수 있습니다.
- 이 코드가 UI가 아닌 계층에 있는 경우 사용하거나 포맷된 예외를 사용하여 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;
}
나도 잠시 이것에 사로잡혔고, 나는 예시와 함께 이용 가능한 모든 오류로 이 요지를 만들었고, 모든 플랫폼 예외 코드를 다룬다
등록 예외 처리 예제
Future<String> signUp(String email, String password, String firstName) async {
FirebaseUser user;
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
user = result.user;
name = user.displayName;
email = user.email;
Firestore.instance.collection('users').document(user.uid).setData({
"uid": user.uid,
"firstName": firstName,
"email": email,
"userImage": userImage,
});
} catch (error) {
switch (error.code) {
case "ERROR_OPERATION_NOT_ALLOWED":
errorMessage = "Anonymous accounts are not enabled";
break;
case "ERROR_WEAK_PASSWORD":
errorMessage = "Your password is too weak";
break;
case "ERROR_INVALID_EMAIL":
errorMessage = "Your email is invalid";
break;
case "ERROR_EMAIL_ALREADY_IN_USE":
errorMessage = "Email is already in use on different account";
break;
case "ERROR_INVALID_CREDENTIAL":
errorMessage = "Your email is invalid";
break;
default:
errorMessage = "An undefined Error happened.";
}
}
if (errorMessage != null) {
return Future.error(errorMessage);
}
return user.uid;
}
로그인 예외 처리 예제
Future<String> signIn(String email, String password) async {
FirebaseUser user;
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
user = result.user;
name = user.displayName;
email = user.email;
userId = user.uid;
} 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;
}
다트에서 구문을 사용하여 다른 예외에 대응할 수 있습니다. 파이어베이스가 자체 플랫폼을 사용하기 때문에다음과 같은 예외 사항으로 쉽게 파악할 수 있습니다:
try {
AuthResult result = await signUp(email, password);
} on PlatformException catch (e) {
print(e.message);
} on Exception catch (e) {
print(e);
}
플랫폼예외는 코드와 함께 UI에 표시할 수 있는 메시지를 가져옵니다:
플랫폼예외(오류_EMAIL_ALREADY_IN_USE, 전자 메일 주소가 이미 다른 계정에서 사용되고 있습니다. null)
인증 클래스에는 다음과 같은 기능이 있습니다:
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;
}
}
위의 catch 오류는 runTime을 반환합니다플랫폼 유형예외 및 플랫폼플러터의 예외에 속성 검사가 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";
});
}
}
또한 최근에 이 오류가 발생했는데 콜백이 디버그 모드(즉, VSCode에서 버튼을 클릭할 때)에서 호출되지 않는다는 것을 알게 되었습니다.
그러나 flot run -d를 입력하면 디버그 모드가 아니기 때문에 메서드가 다시 호출됩니다.
선호하는 시뮬레이터의 코드를 가져오려면 다음 코드 줄을 터미널에 붙여넣으십시오:
instruments -s devices
그래도 문제가 해결되지 않으면 다음을 붙여넣을 수도 있습니다:
xcrun simctl list
이전과 달리 "etcatchError()" 메서드가 호출되고 내부 코드가 예상대로 실행됩니다!
또한 앱은 더 이상 와 충돌하지 않으며 대신 다음과 같은 로그가 표시됩니다:
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The getter 'uid' was called on null.
Receiver: null
나도 구글 사인인에서 이 문제에 직면해 있었는데, 그 문제는 호출되지 않았다!
결론적으로, Firebase Authentication에서 오류를 처리하는 데 약간의 오류가 있다면, 먼저 터미널을 통해 실행을 시도해야 합니다. 고마워요, 그리고 이게 도움이 되었으면 좋겠어요!
나는 API 계층 응답 및 오류 모델을 생성하고 Firebase 플러그인 오류 및 응답 객체를 그 안에 포장하는 것을 선호한다. 이메일과 비밀번호로 로그인하기 위해 나는 이것을 가지고 있다
@override
Future<dynamic> loginWithEmailAndPassword(String email, String password) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return FirebaseSignInWithEmailResponse();
} catch (exception) {
return _mapLoginWithEmailError(exception);
}
}
ApiError _mapLoginWithEmailError(PlatformException error) {
final code = error.code;
if (code == 'ERROR_INVALID_EMAIL') {
return FirebaseSignInWithEmailError(
message: 'Your email is not valid. Please enter a valid email',
type: FirebaseSignInWithEmailErrorType.INVALID_EMAIL);
} else if (code == 'ERROR_WRONG_PASSWORD') {
return FirebaseSignInWithEmailError(
message: 'Your password is incorrect',
type: FirebaseSignInWithEmailErrorType.WRONG_PASSWORD);
} else if (code == 'ERROR_USER_NOT_FOUND') {
return FirebaseSignInWithEmailError(
message: 'You do not have an account. Please Sign Up to'
'proceed',
type: FirebaseSignInWithEmailErrorType.USER_NOT_FOUND);
} else if (code == 'ERROR_TOO_MANY_REQUESTS') {
return FirebaseSignInWithEmailError(
message: 'Did you forget your credentials? Reset your password',
type: FirebaseSignInWithEmailErrorType.TOO_MANY_REQUESTS);
} else if (code == 'ERROR_USER_DISABLED') {
return FirebaseSignInWithEmailError(
message: 'Your account has been disabled. Please contact support',
type: FirebaseSignInWithEmailErrorType.USER_DISABLED);
} else if (code == 'ERROR_OPERATION_NOT_ALLOWED') {
throw 'Email and Password accounts are disabled. Enable them in the '
'firebase console?';
} else {
return FirebaseSignInWithEmailError(
message: 'Make sure you have a stable connection and try again'
type: FirebaseSignInWithEmailErrorType.CONNECTIVITY);
}
}
나는 절대 소방대에서 그것을 반환하지 않는다. 대신 나는 흐름을 듣고 변화가 있으면 그에 따라 대응한다.
예외는 Firebase를 사용하여 처리할 수 있습니다AuthException 클래스입니다.
이메일과 암호를 사용하여 로그인하는 코드는 다음과 같습니다:
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!
}
자신의 논리를 사용하여 오류를 처리할 수 있습니다(예: 경고 대화 상자 표시 등). 사용자를 생성하는 경우에도 동일한 작업을 수행할 수 있습니다.
나는 "Firebase auth"를 사용하여 flurter에서 "firebase platform exception:"과 동일한 오류를 가지고 있으며, 전달 인수에서 try catch 및 trim() 방법을 사용해도 해결되지 않았습니다.
문제는 main.dart에서 "실행" 버튼을 사용하여 앱을 실행할 때 다시 호출되지 않고 오류를 감지한다는 것입니다.
솔루션: Vscode 터미널에 "Flutter run"(디버깅 모드의 경우)을 입력합니다. 또는 "Flutter run --release"(릴리스 모드의 경우)를 선택하면 플랫폼 예외가 발생하지 않습니다.
새로운 답변(18/09/2020)
를 사용하는 경우 오류 코드가 변경되었습니다!
예: is now
나는 그것에 대한 어떤 문서도 찾을 수 없어서 소스 코드로 들어가 모든 오류 코드에 대한 코멘트를 읽었다.
앱에서 모든 오류 코드(예: 확인, 암호 재설정...)를 사용하지 않지만 다음 코드 조각에서 가장 일반적인 오류 코드를 찾을 수 있습니다:
(오래된 오류 코드와 새 오류 코드를 처리합니다
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;
}
}
try {
final newuser = await _auth.createUserWithEmailAndPassword(
email: emailController.text, password: passwordController.text);
// print("Done");
} catch (e) {
print(e);
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(e.message),
actions: <Widget>[
FlatButton(
child: new Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
그래서 나는 오늘 이 문제에 직면했고 표시할 오류 메시지를 하드 코딩하는 대신 문자열 조작을 사용하기로 결정했고 메시지를 간신히 받았다.
목표는 (이후의 모든 것을) 메시지를 받는 것이었다. 예: 이 =>에서 이 =>를 가져옵니다.
그래서 try-catch의 예외를 사용하여 먼저 문자열로 변환한 다음, 처음 14개의 문자('['에서 '/'로)를 아무 것도 사용하지 않고 바꾸었습니다.
그런 다음 '] 패턴을 사용하여 분할 함수를 사용하여 나머지 문자열에서 '] 기호를 검색하고 '] 기호의 인덱스를 피벗으로 하여 전체 문자열을 두 개로 분할합니다. 문자열이 두 개인 목록을 반환합니다. 인덱스 1을 사용하여 오류 메시지인 두 번째 문자열을 가져옵니다.
e.toString().replaceRange(0, 14, '').split(']')[1]
나는 "com.google"을 원하지 않는 문제가 있었다.화력 기지.파이어베이스예외: 내부 오류가 발생했습니다. [ "www.googleapis.com" 호스트를 확인할 수 없음:호스트 이름과 연결된 주소가 없음]"이(가) 사용자에게 사용 중인 백엔드가 Firebase임을 나타냅니다. 그래서 나는 그냥 String().replace All()을 사용했다
Future<void> signIn() async {
final formState = _formkey.currentState;
var _date = DateTime.now();
if (formState!.validate()) {
emailFocus!.unfocus();
passwordFocus!.unfocus();
formState.save();
setState(() {
isloading = true;
_errorMessage = '';
});
try {
UserCredential user = await _firebaseAuth.signInWithEmailAndPassword(
email: _email, password: _password!);
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('email', _email);
await FirebaseFirestore.instance
.collection('Users Token Data')
.doc(user.user!.uid)
.set({'Email': _email, 'Token': _token, 'Date': _date});
Navigator.pushNamedAndRemoveUntil(
context, RouteNames.homePage, (e) => false);
} on FirebaseAuthException catch (e) {
setState(() {
isloading = false;
_errorMessage = e.message.toString().replaceAll(
'com.google.firebase.FirebaseException: An internal error has' +
' occurred. [ Unable to resolve host "www.googleapis.com":' +
"No address associated with hostname ]",
"Please Check Network Connection");
});
print(e.message);
}
}
} }
오류 메시지에서 너무 많은 정보를 노출하고 싶지 않을 경우를 대비하여.
이것을 시도해 보세요, 저는 같은 프로펠러를 가지고 있었고 이 코드는 저와 함께 작동했습니다
catch (e) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Wrong UserName or Password')));
}
Firebase-Auth 최신 버전은 다음 try catch 문을 사용하여 오류 코드 및 오류 메시지를 가져오는 간단한 방법을 제공합니다:
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "name@example.com",
password: "SuperSecretPassword!"
);
} on FirebaseAuthException catch (e) {
print('Failed with error code: ${e.code}');
print(e.message);
}
출처:
버전의 예외 코드를 사용하여 Firebase 인증 예외를 관리합니다
firebase_auth: ^3.3.6
firebase_core: ^1.12.0
다음은 저에게 맞는 코드입니다:
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();
}
}
}
나중에 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 {}
인증 예외를 처리하는 데 문제가 있는 사람에게 도움이 되기를 바랍니다!
이 코드는 "다른 계정에서 사용 중인 사용자"와 같은 예외 원인이 포함된 빨간색 스낵바를 표시합니다.
auth.createUserWithEmailAndPassword(
email: email,
password: password,
).onError((error,stackTrace){
if(error.runtimeType == FirebaseAuthException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(error.toString().replaceRange(0, 14, '').split(']')[1]),
backgroundColor: Theme.of(context).colorScheme.error,
),
);
}
}