如何在 Firebase 中验证电子邮件的真实性?

Mig*_*eso 12 javascript firebase react-native firebase-authentication

我需要在当前代码中添加必要的功能和确切的代码,以便用户在登录之前必须验证电子邮件。

\n

现在,用户注册并自动访问应用程序及其用户面板的所有功能。我想添加必要的功能,以便当用户注册时,显示一条消息,告诉他:您必须验证您的电子邮件,这样我们可以确保它是有效的电子邮件,并避免 SPA 用户注册。

\n

我需要用户验证她的电子邮件才能登录,在她验证之前,她可以像以前一样继续使用该应用程序,而无需登录。

\n

您可以看到我做了几次测试,其他用户试图帮助我,但我们还没有实现必要的目标,因为我需要将功能添加到我现在拥有的代码中,因为这是我知道的唯一方法继续构建我的应用程序。

\n

该应用程序已Firebase通过电子邮件和密码注册,我正在使用它Formik来控制表单的状态并 Yup进行验证。

\n

我已阅读有关“向用户发送验证消息”的 Firebase 文档,

\n

这是 Firebase 函数:

\n
```\nconst auth = getAuth();\nsendEmailVerification(auth.currentUser)\n  .then(() => {\n    // Email verification sent!\n    // ...\n  })\n```\n
Run Code Online (Sandbox Code Playgroud)\n

我现在使用的注册系统是邮件和密码。用户输入电子邮件、密码、验证密码并自动在应用程序中注册。

\n

我做了几次测试,试图将 sendEmailVerification 添加到我的注册系统中,目前我所实现的是确认电子邮件到达用户(SPA 文件夹),但确认电子邮件在用户已经注册并使用该应用程序后到达。

\n

用户必须在收到并确认“确认电子邮件”后才能注册

\n

我需要一个适合我当前应用程序的代码示例,我不具备更改所有代码的知识,这是我的应用程序的基础。

\n

我必须做什么才能正常工作并在用户注册之前收到验证电子邮件?\n我的代码中做错了什么?

\n

我在 GitHub 上展示了该应用程序,以便他们可以看到所有文件

\n

您可以测试该项目,因为它是使用以下命令构建的Expo

\n

exp://exp.host/@miguelitolaparra/restaurantes-5-estrellas?release-channel=default

\n

在此输入图像描述

\n

这是我用来注册用户的方法:

\n
const formik = useFormik({\n    initialValues: initialValues(),\n    validationSchema: validationSchema(), // validate the form data\n    validateOnChange: false,\n    onSubmit: async(formValue) => {\n      try { // send the data to Firebase\n        const auth = getAuth()\n       // sendEmailVerification(auth.currentUser)\n        await createUserWithEmailAndPassword(\n          auth,\n          formValue.email,\n          formValue.password\n        )\n      \n       sendEmailVerification(auth.currentUser)\n\n        navigation.navigate(screen.account.account)\n      } catch (error) {\n        // We use Toast to display errors to the user\n        Toast.show({\n          type: "error",\n          position: "bottom",\n          text1: "Failed to register, please try again later",\n        })\n      }\n    },\n  })\n
Run Code Online (Sandbox Code Playgroud)\n

我还向您展示了完整的文件:

\n
import { useFormik } from \'formik\'\nimport { getAuth, createUserWithEmailAndPassword, sendEmailVerification } from \'firebase/auth\'\n\nexport function RegisterForm() {\n  const [showPassword, setShowPassword] = useState(false)\n  const [showRepeatPassword, setShowRepeatPassword] = useState(false)\n\n  const navigation = useNavigation()\n\n  const formik = useFormik({\n    initialValues: initialValues(),\n    validationSchema: validationSchema(), // validate the form data\n    validateOnChange: false,\n    onSubmit: async (formValue) => {\n      try { // send the data to Firebase\n        const auth = getAuth()\n        //sendEmailVerification(auth.currentUser)\n        await createUserWithEmailAndPassword(\n          auth,\n          formValue.email,\n          formValue.password\n        )\n      sendEmailVerification(auth.currentUser)\n\n       \n        navigation.navigate(screen.account.account)\n      } catch (error) {\n        // We use Toast to display errors to the user\n        Toast.show({\n          type: "error",\n          position: "bottom",\n          text1: "Error al registrarse, intentelo mas tarde",\n        })\n      }\n    },\n  })\n\n  // function to hide or show the password\n  const showHidenPassword = () => setShowPassword((prevState) => !prevState)\n  const showHidenRepeatPassword = () => setShowRepeatPassword((prevState) => !prevState)\n\n  return (\n    // Registration form interface\n    <View>\n      <Input\n        placeholder="Correo electronico"\n        keyboardType="email-address"\n        containerStyle={AuthStyles.input}\n        rightIcon={\n          <Icon type="material-community" name="at" iconStyle={AuthStyles.icon} />\n        }\n        onChangeText={(text) => formik.setFieldValue("email", text)}\n        errorMessage={formik.errors.email}\n      />\n      <Input\n        placeholder="Contrase\xc3\xb1a"\n        containerStyle={AuthStyles.input}\n        secureTextEntry={showPassword ? false : true}\n        rightIcon={\n          <Icon\n            type="material-community"\n            name={showPassword ? "eye-off-outline" : "eye-outline"}\n            iconStyle={AuthStyles.icon}\n            onPress={showHidenPassword}\n          />\n        }\n        onChangeText={(text) => formik.setFieldValue("password", text)}\n        errorMessage={formik.errors.password}\n      />\n      <Input\n        placeholder="Repetir contrase\xc3\xb1a"\n        containerStyle={AuthStyles.input}\n        secureTextEntry={showRepeatPassword ? false : true}\n        rightIcon={\n          <Icon\n            type="material-community"\n            name={showRepeatPassword ? "eye-off-outline" : "eye-outline"}\n            iconStyle={AuthStyles.icon}\n            onPress={showHidenRepeatPassword}\n          />\n        }\n        onChangeText={(text) => formik.setFieldValue("repeatPassword", text)}\n        errorMessage={formik.errors.repeatPassword}\n      />\n      <Button\n        title="REGISTRATE"\n        containerStyle={AuthStyles.btnContainer}\n        buttonStyle={AuthStyles.btn}\n        onPress={formik.handleSubmit} // send the form\n        loading={formik.isSubmitting}// show loading while doing user registration\n      />\n    </View>\n  )\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Yup这是使用RegistreFormValidar.js验证表单的文件

\n
import * as Yup from "yup"\n\n// object that has the elements of the form\nexport function initialValues() {\n  return {\n    email: "",\n    password: "",\n    repeatPassword: "",\n  }\n}\n\n// validate the form data whit Yup\nexport function validationSchema() {\n  return Yup.object({\n    email: Yup.string()\n      .email("El email no es correcto")\n      .required("El email es obligatorio"),\n    password: Yup.string().required("La contrase\xc3\xb1a es obligatoria"),\n  \n    repeatPassword: Yup.string()  // validate that the passwords are the same\n      .required("La contrase\xc3\xb1a es obligatoria")\n      .oneOf([Yup.ref("password")], "Las contrase\xc3\xb1as tienen que ser iguales"),\n  })\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Ays*_*ude -1

据我了解,您需要首先验证用户的电子邮件地址,然后创建用户。阻塞功能也许正是您所需要的。

exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  const locale = context.locale;
  if (user.email && !user.emailVerified) {
    // Send custom email verification on sign-up.
    return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
      return sendCustomVerificationEmail(user.email, link, locale);
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

此 Firebase 函数将在新用户保存到 Firebase 身份验证数据库之前以及令牌返回到客户端应用程序之前触发。但是,我认为该函数执行后,用户就被创建了。为了防止创建用户,您可能必须实现更复杂的流程。

我能想到的一种天真的方法如下:向用户发送电子邮件后,不要终止该功能,并在该功能内部定期检查用户的电子邮件地址是否经过验证。还可以设置超时选项,超时后拒绝用户创建。正如预期的那样,这种方法会增加函数执行时间并且成本高昂。

如果您同意在 Firebase 身份验证数据库中创建用户,我建议实施文档中所述的解决方案。

exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
  const locale = context.locale;
  if (user.email && !user.emailVerified) {
    // Send custom email verification on sign-up.
    return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
      return sendCustomVerificationEmail(user.email, link, locale);
    });
  }
});

exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
 if (user.email && !user.emailVerified) {
   throw new functions.auth.HttpsError(
     'invalid-argument', `"${user.email}" needs to be verified before access is granted.`);
  }
});
Run Code Online (Sandbox Code Playgroud)

这将阻止使用未经验证的电子邮件的用户登录您的应用程序。

检查此文档以了解其他可能的选项:https://firebase.google.com/docs/auth/extend-with-blocking-functions#requiring_email_verification_on_registration