我目前正在构建一个博客示例应用程序,使用 NextJS、ApolloClient 和 MongoDB + MongoRealm。NextJS 骨架是在框架的官方页面教程之后构建的。目前,新用户可以通过访问在“页面/注册”路由的注册表单进行注册。输入他们的凭据后,他们将被重定向到主页。然后,新登录的用户必须访问另一个页面(与“页面/登录”根相关联的页面),该页面包含登录表单,该表单负责他们的电子邮件/密码身份验证。此外,我还设置了 Realm 以向用户的电子邮件地址发送确认电子邮件。该电子邮件包含指向我的 NextJs 应用程序的自定义页面的链接,该页面将处理他们的确认(用户还必须在请求登录后得到确认)
应以此建立工作流程。但是,我想在他/她刚刚登录后自动登录用户(这样他们在创建帐户时就不需要登录并访问登录页面)。
我遇到的问题是我处理用户确认的 React 组件无权访问用户实例的电子邮件和密码。我需要一种登录用户的方法,而无需访问他/她的凭据。
下面,我将尝试准确解释为什么首先会发生这种访问限制。尽管整个 '_app.js' 包含在一些自定义提供程序中,但我会尽量保持简单,因此我将仅介绍本主题所需的内容。
我的 signup.js 文件如下所示:
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;
我的 login.js 文件是根据相同的概念构建的,唯一的区别是 'signUpAndRedirect' 被替换为 'authenticateAndRedirect':
const authenticateAndRedirect = (form) => {
login(form.email, form.password);
router.push("/");
};
这是我的 confirm.js 文件,它负责从确认 URL 中提取令牌和 tokenId。该组件通常仅在客户端收到电子邮件并单击确认链接(基本上具有 /confirm 形式,其中每个令牌是一个字符串并由 Realm 添加到 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;
最后,快速浏览一下我可以通过我的定制提供商访问的注册、登录和确认方法。我非常肯定它们可以正常工作:
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;
currentUser 基本上代表 Realm.app.currentUser 并将由我的提供者提供给 _app。
所以,问题是我的 Confirm 组件无权访问电子邮件和密码字段。我尝试使用 useContext 钩子在兄弟组件之间传递数据,但很快就放弃了这种方法,因为我不想在整个 NextJS 页面中传递敏感数据(我应该使用密码的唯一地方是在MongoDB POST 请求,因为它被 Realm Web 加密)。
有什么办法可以解决这个问题吗?也许是完全不同的方法?
非常感谢您!任何帮助将不胜感激!