KeystoneJS 6后台登录页添加忘记密码功能的最优实现咨询
KeystoneJS 6 密码重置功能最优实现方案
核心思路:自定义Auth页面而非修改依赖文件
直接修改node_modules内的文件会在依赖更新时被覆盖,最优方案是利用Keystone 6提供的自定义Auth页面能力,实现「忘记密码」按钮和完整重置流程,同时兼容内置的邮件发送和密码重置逻辑。
步骤1:创建自定义登录页面(含「忘记密码」按钮)
新建custom-signin.jsx文件,继承默认登录页面并添加模式切换逻辑:
import { useState } from 'react'; import { SigninPage, Button, Field, Label, Input, Alert } from '@keystone-6/auth/pages'; import { gql, useMutation } from '@keystone-6/core/admin-ui/apollo'; // 调用Keystone内置的发送重置链接mutation const FORGOT_PASSWORD_MUTATION = gql` mutation ForgotPassword($email: String!) { sendPasswordResetLink(email: $email) { code message } } `; export default function CustomSigninPage(props) { const [mode, setMode] = useState('signin'); const [email, setEmail] = useState(''); const [error, setError] = useState(''); const [success, setSuccess] = useState(''); const [sendResetLink] = useMutation(FORGOT_PASSWORD_MUTATION); // 处理忘记密码表单提交 const handleForgotPasswordSubmit = async (e) => { e.preventDefault(); setError(''); setSuccess(''); try { const { data } = await sendResetLink({ variables: { email } }); if (data.sendPasswordResetLink.code === 'SUCCESS') { setSuccess('重置链接已发送到你的邮箱,请查收'); } else { setError(data.sendPasswordResetLink.message); } } catch (err) { setError('发送重置链接失败,请稍后重试'); } }; // 忘记密码模式下的页面 if (mode === 'forgot password') { return ( <div style={{ maxWidth: '400px', margin: '2rem auto', padding: '0 1rem' }}> <h2>忘记密码</h2> {error && <Alert tone="negative">{error}</Alert>} {success && <Alert tone="positive">{success}</Alert>} <form onSubmit={handleForgotPasswordSubmit}> <Field label="邮箱"> <Label htmlFor="email">邮箱地址</Label> <Input id="email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} required /> </Field> <div style={{ marginTop: '1rem', display: 'flex', gap: '1rem' }}> <Button type="submit" tone="active">发送重置链接</Button> <Button onClick={() => setMode('signin')} weight="none">返回登录</Button> </div> </form> </div> ); } // 默认登录页面,添加「忘记密码」按钮 return ( <SigninPage {...props}> {({ Form }) => ( <> <Form /> <Button weight="none" tone="active" onClick={() => setMode('forgot password')} style={{ marginTop: '1rem', border: 'none', background: 'transparent', cursor: 'pointer' }} > 忘记密码? </Button> </> )} </SigninPage> ); }
步骤2:在Keystone配置中替换默认登录页面
修改keystone.ts,在auth配置里指定自定义登录页面,同时确保邮件配置正确:
import { config } from '@keystone-6/core'; import { statelessSessions } from '@keystone-6/core/session'; import { createAuth } from '@keystone-6/auth'; import CustomSigninPage from './custom-signin'; const { withAuth } = createAuth({ listKey: 'User', identityField: 'email', secretField: 'password', sessionData: 'name email', initFirstItem: { fields: ['name', 'email', 'password'], }, // 替换默认登录页面 pages: { signin: CustomSigninPage, }, }); export default withAuth( config({ server: { // 确保邮件传输配置正确(你已完成这一步,可根据实际情况调整) email: { transport: { host: 'smtp.example.com', port: 587, auth: { user: 'your-email@example.com', pass: 'your-email-password', }, }, from: 'your-email@example.com', }, }, lists: { User: { fields: { name: { type: 'text', validation: { isRequired: true } }, email: { type: 'text', isIndexed: 'unique', validation: { isRequired: true } }, password: { type: 'password', validation: { isRequired: true } }, }, }, }, session: statelessSessions({ secret: '--your-secure-session-secret--', }), }) );
步骤3:(可选)自定义重置密码页面
如果需要修改默认的重置密码页面样式,可创建custom-reset-password.jsx并在auth配置中指定:
import { ResetPasswordPage } from '@keystone-6/auth/pages'; export default function CustomResetPasswordPage(props) { return ( <div style={{ maxWidth: '400px', margin: '2rem auto', padding: '0 1rem' }}> <h2>重置你的密码</h2> <ResetPasswordPage.Form {...props} /> </div> ); }
然后更新auth的pages配置:
pages: { signin: CustomSigninPage, resetPassword: CustomResetPasswordPage, },
为什么这是最优方案
- 无依赖侵入:不修改
node_modules内文件,避免依赖更新导致代码丢失 - 完全自定义:可根据需求调整UI样式、错误提示等细节
- 兼容内置逻辑:利用Keystone提供的
sendPasswordResetLinkmutation和邮件发送能力,无需从零实现重置流程 - 官方支持:自定义Auth页面是Keystone 6的官方推荐方式,保证版本兼容性
内容的提问来源于stack exchange,提问作者cloudis
相关产品推荐
相关产品推荐

