531 lines
14 KiB
Markdown
531 lines
14 KiB
Markdown
# NextAuth.js (Auth.js) 集成指南
|
||
|
||
## 📋 方案介绍
|
||
|
||
**NextAuth.js** 是最流行的 Next.js 认证解决方案,完全开源免费。
|
||
|
||
### 核心优势
|
||
- ✅ **5分钟集成** - 超级简单
|
||
- ✅ **完全免费** - 无用户数限制
|
||
- ✅ **多种登录方式** - 邮箱、Google、GitHub、微信等
|
||
- ✅ **安全可靠** - OAuth 2.0 标准
|
||
- ✅ **完美集成** - 专为 Next.js 设计
|
||
|
||
---
|
||
|
||
## 🚀 快速集成步骤
|
||
|
||
### 第一步:安装依赖
|
||
|
||
```bash
|
||
cd /Users/lanmu/Desktop/xiaso
|
||
npm install next-auth@latest
|
||
```
|
||
|
||
### 第二步:配置环境变量
|
||
|
||
创建 `.env.local` 文件:
|
||
|
||
```env
|
||
# NextAuth 密钥(必须)
|
||
NEXTAUTH_SECRET=your-secret-key-here-replace-with-random-string
|
||
NEXTAUTH_URL=https://scs.flnxi.com
|
||
|
||
# Google OAuth(可选)
|
||
GOOGLE_CLIENT_ID=your-google-client-id
|
||
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||
|
||
# GitHub OAuth(可选)
|
||
GITHUB_ID=your-github-client-id
|
||
GITHUB_SECRET=your-github-client-secret
|
||
```
|
||
|
||
生成密钥:
|
||
```bash
|
||
openssl rand -base64 32
|
||
```
|
||
|
||
### 第三步:创建 Auth API 路由
|
||
|
||
创建文件:`app/api/auth/[...nextauth]/route.ts`
|
||
|
||
```typescript
|
||
import NextAuth from "next-auth"
|
||
import GoogleProvider from "next-auth/providers/google"
|
||
import GitHubProvider from "next-auth/providers/github"
|
||
import CredentialsProvider from "next-auth/providers/credentials"
|
||
|
||
const handler = NextAuth({
|
||
providers: [
|
||
// 邮箱密码登录
|
||
CredentialsProvider({
|
||
name: 'Credentials',
|
||
credentials: {
|
||
email: { label: "邮箱", type: "email", placeholder: "user@example.com" },
|
||
password: { label: "密码", type: "password" }
|
||
},
|
||
async authorize(credentials, req) {
|
||
// 这里添加您的用户验证逻辑
|
||
// 例如:从数据库查询用户
|
||
const user = { id: "1", name: "用户", email: credentials?.email }
|
||
|
||
if (user) {
|
||
return user
|
||
}
|
||
return null
|
||
}
|
||
}),
|
||
|
||
// Google 登录(需要配置 OAuth)
|
||
GoogleProvider({
|
||
clientId: process.env.GOOGLE_CLIENT_ID!,
|
||
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
||
}),
|
||
|
||
// GitHub 登录(需要配置 OAuth)
|
||
GitHubProvider({
|
||
clientId: process.env.GITHUB_ID!,
|
||
clientSecret: process.env.GITHUB_SECRET!,
|
||
}),
|
||
],
|
||
|
||
// 自定义登录页面
|
||
pages: {
|
||
signIn: '/auth/signin',
|
||
// signOut: '/auth/signout',
|
||
// error: '/auth/error',
|
||
},
|
||
|
||
// 回调函数
|
||
callbacks: {
|
||
async jwt({ token, user }) {
|
||
if (user) {
|
||
token.id = user.id
|
||
}
|
||
return token
|
||
},
|
||
async session({ session, token }) {
|
||
if (session.user) {
|
||
session.user.id = token.id as string
|
||
}
|
||
return session
|
||
},
|
||
},
|
||
|
||
// 会话策略
|
||
session: {
|
||
strategy: "jwt",
|
||
maxAge: 30 * 24 * 60 * 60, // 30 天
|
||
},
|
||
})
|
||
|
||
export { handler as GET, handler as POST }
|
||
```
|
||
|
||
### 第四步:创建登录页面
|
||
|
||
创建文件:`app/auth/signin/page.tsx`
|
||
|
||
```typescript
|
||
'use client'
|
||
|
||
import { signIn } from 'next-auth/react'
|
||
import { useState } from 'react'
|
||
import { Mail, Lock, Chrome, Github } from 'lucide-react'
|
||
|
||
export default function SignInPage() {
|
||
const [email, setEmail] = useState('')
|
||
const [password, setPassword] = useState('')
|
||
const [loading, setLoading] = useState(false)
|
||
|
||
const handleSubmit = async (e: React.FormEvent) => {
|
||
e.preventDefault()
|
||
setLoading(true)
|
||
|
||
await signIn('credentials', {
|
||
email,
|
||
password,
|
||
callbackUrl: '/',
|
||
})
|
||
|
||
setLoading(false)
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen bg-gradient-to-b from-apple-gray-50 to-white flex items-center justify-center px-4">
|
||
<div className="max-w-md w-full">
|
||
{/* Logo */}
|
||
<div className="text-center mb-8">
|
||
<h1 className="text-3xl font-bold text-apple-gray-900 mb-2">
|
||
登录 FLNXI
|
||
</h1>
|
||
<p className="text-apple-gray-600">
|
||
欢迎回来,请登录您的账户
|
||
</p>
|
||
</div>
|
||
|
||
{/* 登录卡片 */}
|
||
<div className="bg-white rounded-2xl apple-shadow-lg p-8">
|
||
{/* 邮箱密码登录 */}
|
||
<form onSubmit={handleSubmit} className="space-y-4 mb-6">
|
||
<div>
|
||
<label className="block text-sm font-medium text-apple-gray-700 mb-2">
|
||
邮箱地址
|
||
</label>
|
||
<div className="relative">
|
||
<Mail className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-apple-gray-400" />
|
||
<input
|
||
type="email"
|
||
value={email}
|
||
onChange={(e) => setEmail(e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-apple-gray-200 rounded-xl focus:ring-2 focus:ring-apple-blue focus:border-transparent outline-none"
|
||
placeholder="your@email.com"
|
||
required
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label className="block text-sm font-medium text-apple-gray-700 mb-2">
|
||
密码
|
||
</label>
|
||
<div className="relative">
|
||
<Lock className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-apple-gray-400" />
|
||
<input
|
||
type="password"
|
||
value={password}
|
||
onChange={(e) => setPassword(e.target.value)}
|
||
className="w-full pl-10 pr-4 py-3 border border-apple-gray-200 rounded-xl focus:ring-2 focus:ring-apple-blue focus:border-transparent outline-none"
|
||
placeholder="••••••••"
|
||
required
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<button
|
||
type="submit"
|
||
disabled={loading}
|
||
className="w-full py-3 bg-gradient-to-r from-apple-blue to-blue-600 text-white font-semibold rounded-xl button-hover apple-shadow disabled:opacity-50"
|
||
>
|
||
{loading ? '登录中...' : '登录'}
|
||
</button>
|
||
</form>
|
||
|
||
{/* 分割线 */}
|
||
<div className="relative my-6">
|
||
<div className="absolute inset-0 flex items-center">
|
||
<div className="w-full border-t border-apple-gray-200" />
|
||
</div>
|
||
<div className="relative flex justify-center text-sm">
|
||
<span className="px-4 bg-white text-apple-gray-500">
|
||
或使用第三方登录
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 第三方登录 */}
|
||
<div className="space-y-3">
|
||
<button
|
||
onClick={() => signIn('google', { callbackUrl: '/' })}
|
||
className="w-full flex items-center justify-center space-x-3 py-3 border-2 border-apple-gray-200 rounded-xl hover:bg-apple-gray-50 transition-all font-medium"
|
||
>
|
||
<Chrome className="w-5 h-5 text-red-500" />
|
||
<span>使用 Google 登录</span>
|
||
</button>
|
||
|
||
<button
|
||
onClick={() => signIn('github', { callbackUrl: '/' })}
|
||
className="w-full flex items-center justify-center space-x-3 py-3 border-2 border-apple-gray-200 rounded-xl hover:bg-apple-gray-50 transition-all font-medium"
|
||
>
|
||
<Github className="w-5 h-5" />
|
||
<span>使用 GitHub 登录</span>
|
||
</button>
|
||
</div>
|
||
|
||
{/* 底部链接 */}
|
||
<div className="mt-6 text-center text-sm text-apple-gray-600">
|
||
还没有账户?
|
||
<a href="/auth/signup" className="text-apple-blue hover:underline ml-1">
|
||
立即注册
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 返回首页 */}
|
||
<div className="text-center mt-6">
|
||
<a href="/" className="text-apple-gray-600 hover:text-apple-blue transition-colors">
|
||
← 返回首页
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 第五步:添加 Session Provider
|
||
|
||
修改 `app/layout.tsx`:
|
||
|
||
```typescript
|
||
import { getServerSession } from "next-auth/next"
|
||
import SessionProvider from '@/components/SessionProvider'
|
||
|
||
export default async function RootLayout({
|
||
children,
|
||
}: {
|
||
children: React.ReactNode
|
||
}) {
|
||
const session = await getServerSession()
|
||
|
||
return (
|
||
<html lang="zh-CN">
|
||
<body>
|
||
<SessionProvider session={session}>
|
||
{children}
|
||
</SessionProvider>
|
||
</body>
|
||
</html>
|
||
)
|
||
}
|
||
```
|
||
|
||
创建 `components/SessionProvider.tsx`:
|
||
|
||
```typescript
|
||
'use client'
|
||
|
||
import { SessionProvider as NextAuthSessionProvider } from 'next-auth/react'
|
||
|
||
export default function SessionProvider({
|
||
children,
|
||
session,
|
||
}: {
|
||
children: React.ReactNode
|
||
session: any
|
||
}) {
|
||
return (
|
||
<NextAuthSessionProvider session={session}>
|
||
{children}
|
||
</NextAuthSessionProvider>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 第六步:在 Header 中添加登录按钮
|
||
|
||
修改 `components/Header.tsx`,添加登录状态:
|
||
|
||
```typescript
|
||
'use client'
|
||
|
||
import { useSession, signIn, signOut } from 'next-auth/react'
|
||
import { User, LogOut } from 'lucide-react'
|
||
|
||
export default function Header({ scrolled }: HeaderProps) {
|
||
const { data: session, status } = useSession()
|
||
|
||
return (
|
||
<header>
|
||
{/* ... 其他代码 ... */}
|
||
|
||
{/* 添加登录/用户信息 */}
|
||
<div className="flex items-center space-x-4">
|
||
{status === 'loading' ? (
|
||
<div className="w-8 h-8 rounded-full bg-apple-gray-200 animate-pulse" />
|
||
) : session ? (
|
||
// 已登录
|
||
<div className="flex items-center space-x-3">
|
||
<span className="text-sm text-apple-gray-700">
|
||
{session.user?.name || session.user?.email}
|
||
</span>
|
||
<button
|
||
onClick={() => signOut()}
|
||
className="flex items-center space-x-2 px-4 py-2 text-apple-gray-700 hover:text-apple-blue transition-colors"
|
||
>
|
||
<LogOut className="w-4 h-4" />
|
||
<span>退出</span>
|
||
</button>
|
||
</div>
|
||
) : (
|
||
// 未登录
|
||
<button
|
||
onClick={() => signIn()}
|
||
className="flex items-center space-x-2 px-5 py-2 bg-apple-blue text-white rounded-full text-sm font-medium button-hover apple-shadow"
|
||
>
|
||
<User className="w-4 h-4" />
|
||
<span>登录</span>
|
||
</button>
|
||
)}
|
||
</div>
|
||
</header>
|
||
)
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎨 高级功能
|
||
|
||
### 1. 添加注册页面
|
||
|
||
创建 `app/auth/signup/page.tsx`(类似登录页面)
|
||
|
||
### 2. 保护页面(需要登录才能访问)
|
||
|
||
```typescript
|
||
// app/dashboard/page.tsx
|
||
import { getServerSession } from "next-auth/next"
|
||
import { redirect } from "next/navigation"
|
||
|
||
export default async function DashboardPage() {
|
||
const session = await getServerSession()
|
||
|
||
if (!session) {
|
||
redirect('/auth/signin')
|
||
}
|
||
|
||
return <div>受保护的页面内容</div>
|
||
}
|
||
```
|
||
|
||
### 3. 添加微信登录
|
||
|
||
```bash
|
||
npm install next-auth-wechat
|
||
```
|
||
|
||
```typescript
|
||
// 在 [...nextauth]/route.ts 中添加
|
||
import WeChatProvider from "next-auth-wechat"
|
||
|
||
providers: [
|
||
WeChatProvider({
|
||
clientId: process.env.WECHAT_APP_ID!,
|
||
clientSecret: process.env.WECHAT_APP_SECRET!,
|
||
}),
|
||
]
|
||
```
|
||
|
||
---
|
||
|
||
## 📦 部署配置
|
||
|
||
### 1. 更新环境变量
|
||
|
||
在服务器上设置环境变量:
|
||
|
||
```bash
|
||
ssh root@45.249.208.118
|
||
|
||
# 编辑环境变量
|
||
cd /opt/flnxi-website
|
||
nano .env.local
|
||
```
|
||
|
||
添加:
|
||
```env
|
||
NEXTAUTH_SECRET=<生成的密钥>
|
||
NEXTAUTH_URL=https://scs.flnxi.com
|
||
```
|
||
|
||
### 2. 更新 Docker 配置
|
||
|
||
修改 `docker-compose.yml`:
|
||
|
||
```yaml
|
||
services:
|
||
web:
|
||
build:
|
||
context: .
|
||
dockerfile: Dockerfile
|
||
ports:
|
||
- "4782:3000"
|
||
environment:
|
||
- NODE_ENV=production
|
||
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||
- NEXTAUTH_URL=${NEXTAUTH_URL}
|
||
env_file:
|
||
- .env.local
|
||
restart: unless-stopped
|
||
```
|
||
|
||
### 3. 重新构建部署
|
||
|
||
```bash
|
||
docker-compose down
|
||
docker-compose up -d --build
|
||
```
|
||
|
||
---
|
||
|
||
## 🔐 配置第三方登录
|
||
|
||
### Google OAuth 配置
|
||
|
||
1. 访问 [Google Cloud Console](https://console.cloud.google.com/)
|
||
2. 创建新项目
|
||
3. 启用 Google+ API
|
||
4. 创建 OAuth 2.0 凭据
|
||
5. 添加授权重定向 URI:`https://scs.flnxi.com/api/auth/callback/google`
|
||
|
||
### GitHub OAuth 配置
|
||
|
||
1. 访问 [GitHub Settings > Developer settings](https://github.com/settings/developers)
|
||
2. 创建 New OAuth App
|
||
3. 添加授权回调 URL:`https://scs.flnxi.com/api/auth/callback/github`
|
||
|
||
---
|
||
|
||
## 📊 功能对比
|
||
|
||
| 功能 | NextAuth.js | Clerk | Logto |
|
||
|------|-------------|-------|-------|
|
||
| 开源免费 | ✅ | ⚠️ 有限制 | ✅ |
|
||
| 集成难度 | 简单 | 超简单 | 中等 |
|
||
| 用户数限制 | 无限制 | 10k MAU | 无限制 |
|
||
| UI 自定义 | 完全自定义 | 有限 | 可自定义 |
|
||
| 中文支持 | 需自己实现 | 支持 | 原生支持 |
|
||
| 需要额外服务 | ❌ | ❌ | ✅ |
|
||
|
||
---
|
||
|
||
## ✅ 集成检查清单
|
||
|
||
- [ ] 安装 next-auth 依赖
|
||
- [ ] 创建 API 路由 `[...nextauth]/route.ts`
|
||
- [ ] 配置环境变量(NEXTAUTH_SECRET)
|
||
- [ ] 创建登录页面
|
||
- [ ] 添加 SessionProvider
|
||
- [ ] 更新 Header 组件
|
||
- [ ] 测试邮箱登录
|
||
- [ ] (可选)配置 Google OAuth
|
||
- [ ] (可选)配置 GitHub OAuth
|
||
- [ ] 部署到服务器
|
||
- [ ] 测试生产环境
|
||
|
||
---
|
||
|
||
## 🎯 推荐时间线
|
||
|
||
- **5分钟**:基础集成(邮箱登录)
|
||
- **+10分钟**:美化登录页面
|
||
- **+15分钟**:添加 Google/GitHub 登录
|
||
- **+10分钟**:测试和部署
|
||
|
||
**总计:40分钟完成完整集成**
|
||
|
||
---
|
||
|
||
## 📞 获取帮助
|
||
|
||
如果遇到问题:
|
||
1. 查看 [NextAuth.js 官方文档](https://next-auth.js.org/)
|
||
2. 搜索 [GitHub Issues](https://github.com/nextauthjs/next-auth/issues)
|
||
3. 加入 [Discord 社区](https://discord.gg/nextauth)
|
||
|
||
---
|
||
|
||
**准备好了吗?让我开始帮您集成!** 🚀
|
||
|