凭据提供商与自定义登录
使用凭据提供商和自定义登录表单,根据数据库验证用户身份。
凭据提供商与自定义登录 是 CoddyKit 上的免费 React Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
何时使用凭据提供商
当您要针对自己的数据库进行身份验证(电子邮件加密码),而不是使用 OAuth 提供商时,请使用凭据提供商。您必须谨慎处理密码哈希和安全问题。
定义凭据提供商
将 Credentials 添加到提供商数组中。authorize 函数会接收提交的凭据,并返回用户对象或 null。
import Credentials from 'next-auth/providers/credentials';
import bcrypt from 'bcryptjs';
export const { handlers, auth } = NextAuth({
providers: [
Credentials({
name: 'Credentials',
credentials: {
email: { label: 'Email', type: 'email' },
password: { label: 'Password', type: 'password' },
},
async authorize(credentials) {
const user = await db.user.findUnique({ where: { email: credentials.email as string } });
if (!user) return null;
const valid = await bcrypt.compare(credentials.password as string, user.passwordHash);
if (!valid) return null;
return { id: user.id, name: user.name, email: user.email };
},
}),
],
});自定义登录表单
将登录表单构建为客户端组件,并从 next-auth/react 调用 signIn('credentials', { email, password })。
'use client';
import { signIn } from 'next-auth/react';
export function LoginForm() {
const [error, setError] = useState('');
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const form = new FormData(e.currentTarget);
const result = await signIn('credentials', {
email: form.get('email'),
password: form.get('password'),
redirect: false, // handle redirect manually
});
if (result?.error) setError('Invalid email or password');
else router.push('/dashboard');
}
return (
<form onSubmit={handleSubmit}>
{error && <p className="error">{error}</p>}
<input name="email" type="email" required />
<input name="password" type="password" required />
<button type="submit">Sign in</button>
</form>
);
}使用 redirect: false 处理错误
向 signIn() 传入 redirect: false,即可接收结果对象,并在组件中处理错误,而不是被重定向到错误页面。
const result = await signIn('credentials', { email, password, redirect: false });
if (result?.error) {
// result.error is 'CredentialsSignin' for auth failures
setError('Invalid email or password');
}在 authorize 中使用 Zod 验证
在访问数据库之前,在 authorize 函数中使用 Zod 验证凭据。
import { z } from 'zod';
const schema = z.object({ email: z.string().email(), password: z.string().min(8) });
async authorize(credentials) {
const parsed = schema.safeParse(credentials);
if (!parsed.success) return null;
const { email, password } = parsed.data;
// ... db lookup
}凭据的会话策略
凭据提供程序要求使用 JWT 会话策略(会话无需数据库适配器)。请明确设置 session: { strategy: 'jwt' }。
export const { handlers, auth } = NextAuth({
session: { strategy: 'jwt' },
providers: [Credentials({ ... })],
});向会话添加自定义字段
通过 JWT 和会话回调传递额外的用户数据,以便在 useSession() 中获取这些数据。
callbacks: {
async jwt({ token, user }) {
if (user) { token.id = user.id; token.role = user.role; }
return token;
},
async session({ session, token }) {
session.user.id = token.id as string;
session.user.role = token.role as string;
return session;
},
},密码哈希
存储密码前,请始终使用 bcrypt 对其进行哈希处理。绝不要存储明文密码。
import bcrypt from 'bcryptjs';
// On registration:
const passwordHash = await bcrypt.hash(password, 12);
await db.user.create({ data: { email, passwordHash } });
// On login (in authorize):
const valid = await bcrypt.compare(submittedPassword, user.passwordHash);限制登录尝试次数
请使用中间件或内存存储限制登录尝试次数,以保护凭据端点免受暴力破解。
// middleware.ts or in a rate-limiting library
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, '10 s') });
// Check in authorize before DB query:
const { success } = await ratelimit.limit(credentials.email as string);
if (!success) return null;注册流程
注册独立于 Auth.js — 请通过服务器操作或 API 路由将用户创建到数据库中(密码需经过哈希处理),然后使用 signIn('credentials', ...) 为其登录。
快速检查
在自定义登录表单中调用 signIn() 时,为什么应传入 redirect: false?
回顾
凭据提供程序会将提交的表单数据传递给您的 authorize 函数。请使用 Zod 验证数据,使用 bcrypt 比较哈希后的密码,并返回用户对象或 null。在表单中使用 redirect: false 以便自定义处理错误,并始终将凭据与 JWT 策略结合使用。
常见问题解答
「凭据提供商与自定义登录」课时是免费的吗?
是的 — 「凭据提供商与自定义登录」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「凭据提供商与自定义登录」这节课中我会学到什么?
使用凭据提供商和自定义登录表单,根据数据库验证用户身份。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「凭据提供商与自定义登录」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。