Authentication 如何在电子邮件/密码验证后自动登录用户
我目前正在使用NextJS、ApolloClient和MongoDB+MongoRealm构建一个博客示例应用程序。NextJS框架是在框架的官方页面教程之后构建的。 目前,新用户可以通过访问发送到“pages/signup”的注册表单进行注册。输入凭据后,他们将被重定向到主页。然后,新登录的用户必须访问另一个页面,即与“pages/login”root相关联的页面,该页面包含登录表单,该表单负责对其电子邮件/密码进行身份验证。 此外,我还设置了Realm,以便在用户的电子邮件地址发送确认电子邮件。该电子邮件包含一个指向my NextJs应用程序自定义页面的链接,该页面将处理他们的确认请求,用户在请求登录后也必须进行确认 工作流程应以此为基础建立。但是,我想在用户刚刚登录后自动登录,这样他们在创建帐户时就不需要登录,也不需要访问登录页面 我遇到的问题是,处理用户确认的React组件无法访问用户实例的电子邮件和密码。我需要一种方法来登录用户,而不必访问他/她的凭据 下面,我将尝试解释为什么首先会发生这种访问限制。尽管整个“_app.js”都封装在一些定制的提供者中,但我会尽量让事情尽可能简单,所以我只介绍本主题所需的内容 我的signup.js文件如下所示:Authentication 如何在电子邮件/密码验证后自动登录用户,authentication,next.js,mongodb-realm,Authentication,Next.js,Mongodb Realm,我目前正在使用NextJS、ApolloClient和MongoDB+MongoRealm构建一个博客示例应用程序。NextJS框架是在框架的官方页面教程之后构建的。 目前,新用户可以通过访问发送到“pages/signup”的注册表单进行注册。输入凭据后,他们将被重定向到主页。然后,新登录的用户必须访问另一个页面,即与“pages/login”root相关联的页面,该页面包含登录表单,该表单负责对其电子邮件/密码进行身份验证。 此外,我还设置了Realm,以便在用户的电子邮件地址发送确认电子邮
import { useForm } from "react-hook-form";
// Used 'useForm' hook to simplify data extraction from the //input form
import { useAuth } from "members";
const SignUpForm = () => {
const router = useRouter();
const { handleSubmit, register } = useForm();
const { signup } = useAuth();
const signUpAndRedirect = (form) => {
signup(form.email, form.password);
router.push("/");
// after signing up, redirect client back to home
};
return (
{/*My form's 'email' and 'password' fields are only accessible in the SignUpForm component*/}
<div>
<form onSubmit={handleSubmit(signUpAndRedirect)}>
...
...
</form>
</div>
);
};
export default SignUpForm;
下面是我的confirm.js文件,它负责从确认URL中提取令牌和令牌ID。此组件通常仅在客户端收到电子邮件并单击确认链接时呈现,该链接基本上具有表单/confirm,其中每个令牌都是一个字符串,并按领域添加到URL中
import Link from "next/link";
import { useEffect } from "react";
import { useRouter } from "next/router";
import { useAuth } from "members";
const Confirm = () => {
const router = useRouter();
const { confirm, login } = useAuth();
useEffect(() => {
const token = router.query.token;
const tokenId = router.query.tokenId;
if (token && tokenId) {
confirm(token, tokenId);
login(email, password); // !!! I don't have access to these
}
}, [router]);
//used useEffect() to assure the confirmation only happens once, after the component was rendered.
return (
<div>
<h2>
Thank you for confirming your email. Your profile was successfully
activated.
</h2>
<Link href="/">
<a>Go back to home</a>
</Link>
</div>
);
};
export default Confirm;
currentUser基本上代表Realm.app.currentUser,并由我的提供商提供给_应用程序
所以,问题是我的确认组件没有访问电子邮件和密码字段的权限。
我曾尝试使用useContext钩子在同级组件之间传递数据,但很快就放弃了这种方法,因为我不想在整个NextJS页面中传递敏感数据。我应该使用密码的唯一地方是MongoDB POST请求期间,因为它由Realm Web加密
我有办法解决这个问题吗?也许是完全不同的方法
提前非常感谢!任何帮助都将不胜感激 如果禁用用户电子邮件确认,则可能会在注册完成后调用登录功能,如下所示: registerAndLoginemail,密码 .然后=> 登录电子邮件、密码 .then=>router.push'/' .catcherr=>抛出错误 .catcherr=>抛出错误 我用你的帖子解决了我的一个错误,所以顺便谢谢你。
希望我的答案有效,我没有时间测试。在后端进行身份验证。您需要对照数据库中存储的散列密码检查普通用户密码。您可以在本地存储由auth MethodsHanks生成的令牌以供评论!:事实上,这通常发生在服务器上。但是,ApolloClient和MongoDB Realm使用捆绑到NextJs应用程序中的一些依赖项和node.js包,为您提供了直接从客户端进行身份验证的机会。Apollo客户端基本上使用GraphQL和Mongo领域接口进行查询,Mongo领域接口反过来与Atlas进行通信。我不会将密码存储到Atlas中。目前,我将它们存储在Realm中,但在过渡到JWT身份验证后,情况会有所改变。我已经成功地在我的应用程序中创建并验证了用户,唯一的问题是我希望用户在创建帐户后立即登录。这不是一个重要的问题,但是,如果我找不到任何新的方法,也许我会让它保持这种状态。你可以找到更多关于ApolloClient的信息,并在这里作出反应:整个Mongo相关的文档非常稀少,但是,通关有点痛苦,Benjamin!谢谢你的回答!很高兴你发现我的帖子很有用最后,我不得不使用Google Firebase身份验证,因此用户创建过程现在由该服务处理。不过,我会在完成更紧急的事情后尝试你的想法。我认为它更简单,通常只是在确认后将用户重定向到登录页面。所以只需一个router.push/login就足够了。您是否可以提供完整的身份验证useAuth&&useRealm代码,因为关于领域身份验证的文档太少了。。。不过你似乎挺成功的。也许我还必须切换到Firebase,因为它有更多的文档!当然没问题!这是我的Git:我得到了一些帮助 我的一些有经验的朋友但关键是将整个应用程序包装在一个“领域提供程序”、“Apollo客户端提供程序”和一个“缓存提供程序”中。这是因为你必须在整个应用程序中访问当前用户相关信息。此外,如果没有领域实例,您将无法与Mongo对话。但是,为了确保一切都清楚,最好是克隆我的repo,运行“npm install”,并尝试按照代码进行操作。您可以查看相应的分支,了解您需要的信息。请随时问我任何问题:。
import Link from "next/link";
import { useEffect } from "react";
import { useRouter } from "next/router";
import { useAuth } from "members";
const Confirm = () => {
const router = useRouter();
const { confirm, login } = useAuth();
useEffect(() => {
const token = router.query.token;
const tokenId = router.query.tokenId;
if (token && tokenId) {
confirm(token, tokenId);
login(email, password); // !!! I don't have access to these
}
}, [router]);
//used useEffect() to assure the confirmation only happens once, after the component was rendered.
return (
<div>
<h2>
Thank you for confirming your email. Your profile was successfully
activated.
</h2>
<Link href="/">
<a>Go back to home</a>
</Link>
</div>
);
};
export default Confirm;
const client = () => {
const { app, credentials } = useRealm();
const [currentUser, setCurrentUser] = useState(app.currentUser || false);
const [isAuthenticated, setIsAuthenticated] = useState(user ? true : false);
// Login and logout using email/password.
const login = async (email, password) => {
try {
const userCredentials = await credentials(email, password);
await app.logIn(userCredentials);
setCurrentUser(app.currentUser);
setIsAuthenticated(true);
} catch (e) {
throw e;
}
};
const logout = async () => {
try {
setUser(null);
// Sign out from Realm and Auth0.
await app.currentUser?.logOut();
// Update the user object.
setCurrentUser(app.currentUser);
setIsAuthenticated(false);
setUser(false);
} catch (e) {
throw e;
}
};
const signup = async (email, password) => {
try {
await app.emailPasswordAuth.registerUser(email, password);
// await app.emailPasswordAuth.resendConfirmation(email);
} catch (e) {
throw e;
}
};
const confirm = async (token, tokenId) => {
try {
await app.emailPasswordAuth.confirmUser(token, tokenId);
} catch (e) {
throw e;
}
};
return {
currentUser,
login,
logout,
signup,
confirm,
};
};
export default client;