A/B 测试设计与分析时使用。适用于产品实验、功能验证、转化率优化。融合假设驱动 + 样本量计算 + 置信度判断。
日本語の概要は準備中です。原文の説明を表示しています。
端到端认证实现时使用。适用于注册 → 登录 → Token → 权限 → 前端守卫的全栈闭环。覆盖 NextAuth / Lucia / Supabase Auth / 自建 JWT。
インストールする前に、エージェントに与えられる指示の中身を確認できます。
1. 认证是端到端的
DB users 表 + 后端 JWT + 前端守卫 = 一起做
2. 不自己写加密
用 bcrypt / argon2
3. Token 存储安全
HttpOnly Cookie(推荐)> localStorage
4. 前端守卫 ≠ 安全
后端必须校验,前端只是 UX
5. 用现成方案优先
NextAuth / Lucia / Supabase Auth > 自建
| 方案 | 适合 | 复杂度 |
|---|---|---|
| NextAuth.js (Auth.js) | Next.js 项目 | 低 |
| Lucia | 任意 TS 框架 | 中 |
| Supabase Auth | Supabase 项目 | 低 |
| Clerk | SaaS(付费) | 极低 |
| 自建 JWT | 完全控制 | 高 |
| Django Auth | Django 项目 | 低 |
| Devise | Rails 项目 | 低 |
// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import GoogleProvider from 'next-auth/providers/google';
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
CredentialsProvider({
async authorize(credentials) {
const user = await db.user.findUnique({ where: { email: credentials.email } });
if (!user) return null;
const valid = await bcrypt.compare(credentials.password, user.password);
if (!valid) return null;
return { id: user.id, email: user.email, role: user.role };
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) { token.role = user.role; token.id = user.id; }
return token;
},
async session({ session, token }) {
session.user.role = token.role;
session.user.id = token.id;
return session;
},
},
});
// 注册
app.post('/auth/register', async (req, res) => {
const { email, password, name } = registerSchema.parse(req.body);
const hash = await bcrypt.hash(password, 12);
const user = await db.user.create({ data: { email, password: hash, name } });
const token = generateAccessToken(user);
const refresh = generateRefreshToken(user);
await db.refreshToken.create({ data: { token: refresh, userId: user.id } });
res.cookie('refresh_token', refresh, { httpOnly: true, secure: true, sameSite: 'lax', maxAge: 7 * 24 * 60 * 60 * 1000 });
res.json({ accessToken: token, user: { id: user.id, email, name } });
});
// 登录
app.post('/auth/login', async (req, res) => {
const { email, password } = loginSchema.parse(req.body);
const user = await db.user.findUnique({ where: { email } });
if (!user || !(await bcrypt.compare(password, user.password))) {
return res.status(401).json({ error: { code: 'INVALID_CREDENTIALS' } });
}
// ... 同上生成 token
});
// 刷新
app.post('/auth/refresh', async (req, res) => {
const refreshToken = req.cookies.refresh_token;
if (!refreshToken) return res.status(401).json({ error: { code: 'NO_REFRESH_TOKEN' } });
const stored = await db.refreshToken.findUnique({ where: { token: refreshToken } });
if (!stored) return res.status(401).json({ error: { code: 'INVALID_REFRESH_TOKEN' } });
const user = await db.user.findUnique({ where: { id: stored.userId } });
const newAccess = generateAccessToken(user);
res.json({ accessToken: newAccess });
});
// 中间件
function authMiddleware(req, res, next) {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).json({ error: { code: 'UNAUTHORIZED' } });
try {
req.user = jwt.verify(token, process.env.JWT_SECRET);
next();
} catch {
return res.status(401).json({ error: { code: 'TOKEN_EXPIRED' } });
}
}
// 登录
async function login(email: string, password: string) {
const res = await api.post('/auth/login', { email, password });
setAccessToken(res.data.accessToken);
setUser(res.data.user);
router.push('/dashboard');
}
// Token 刷新(axios 拦截器)
api.interceptors.response.use(
(res) => res,
async (error) => {
if (error.response?.status === 401 && !error.config._retry) {
error.config._retry = true;
const { data } = await api.post('/auth/refresh');
setAccessToken(data.accessToken);
error.config.headers.Authorization = `Bearer ${data.accessToken}`;
return api(error.config);
}
return Promise.reject(error);
}
);
// 路由守卫(Next.js middleware)
export function middleware(request: NextRequest) {
const token = request.cookies.get('access_token');
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
}
1. DB:users 表(email, password_hash, role)
2. 后端:注册 / 登录 / 刷新 / 中间件
3. 前端:登录表单 / Token 存储 / 路由守卫
4. 联调:Token 传递 / 刷新 / 过期处理
5. 测试:登录成功 / 失败 / 越权
templates/auth-checklist.md — 认证端到端清单□ 密码 bcrypt / argon2
□ JWT 有过期时间(15 min)
□ Refresh Token 可撤销
□ Token 存 HttpOnly Cookie
□ 前端路由守卫
□ 后端中间件校验
□ 角色权限检查
□ 资源归属检查
□ 登录失败不暴露存在性
□ 社交登录(如需)
□ 测试覆盖(登录 / 越权)
上游:
database-schema-impl → users 表
下游:
api-frontend-integration → Token 联调
e2e-feature-delivery → 认证是功能的一部分
backend-engineer auth-implementation(深度)
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
A/B 测试设计与分析时使用。适用于产品实验、功能验证、转化率优化。融合假设驱动 + 样本量计算 + 置信度判断。
日本語の概要は準備中です。原文の説明を表示しています。
上线前业务方/产品方验收时使用。适用于功能交付确认、UAT、发布会签。融合 BDD Given-When-Then、Specification by Example、ATDD。
日本語の概要は準備中です。原文の説明を表示しています。
设计无障碍可访问的界面时使用。适用于满足 WCAG 标准、键盘导航、屏幕阅读器支持。优先使用 WCAG 2.2 AA 级标准 + 键盘 + 焦点 + 对比度 + ARIA。
日本語の概要は準備中です。原文の説明を表示しています。
实现可访问性(无障碍)时使用。覆盖 WCAG 2.2 AA / ARIA / 键盘导航 / 屏幕阅读器 / 颜色对比 / 焦点管理。融合 React Aria / Radix UI / Headless UI 实践 + axe-core 自动化测试。
日本語の概要は準備中です。原文の説明を表示しています。
AI 模型部署时使用。适用于推理服务 / GPU / TensorRT / 监控 / 扩缩容。
日本語の概要は準備中です。原文の説明を表示しています。
数据分析报告输出时使用。适用于业务分析报告、周报、专项分析、决策支持。融合洞察 + 建议 + 行动项。
日本語の概要は準備中です。原文の説明を表示しています。