认证系统接入指南
完整的 Athena 认证系统使用指南,包含 OAuth 配置、API 使用、安全最佳实践和代码示例
🚀 快速开始
1
配置 OAuth
设置 GitHub、Google 等 OAuth 应用
2
集成 API
使用认证 API 和中间件
3
部署上线
配置生产环境和安全设置
📋 系统概述
认证架构
Athena 采用基于 JWT 的无状态认证系统,支持多种 OAuth 提供商,提供完整的会话管理和安全控制。
核心特性
🔐 多提供商支持
- • GitHub OAuth
- • Google OAuth
- • Microsoft OAuth
- • Gitee OAuth
🛡️ 安全特性
- • JWT 令牌认证
- • 会话管理
- • CSRF 保护
- • 安全 Cookie
⚡ 开发体验
- • 类型安全
- • 中间件支持
- • 简单集成
- • 完整文档
📊 管理功能
- • 用户信息管理
- • 会话监控
- • 设备管理
- • 安全日志
认证流程
1
用户点击登录
→
2
重定向到 OAuth
→
3
授权回调
→
4
生成 JWT
→
5
设置 Cookie
⚙️ OAuth 配置
GitHub OAuth 配置
1. 创建 GitHub OAuth 应用
- 访问 GitHub Developer Settings
- 点击 "New OAuth App"
- 填写应用信息:
- Application name: 你的应用名称
- Homepage URL:
https://yourdomain.com - Authorization callback URL:
https://yourdomain.com/api/auth/callback?provider=github
- 获取 Client ID 和 Client Secret
2. 环境变量配置
# GitHub OAuth 配置 GITHUB_CLIENT_ID=your_github_client_id GITHUB_CLIENT_SECRET=your_github_client_secret # 基础配置 BASE_URL=https://yourdomain.com JWT_SECRET=your_jwt_secret_key SESSION_EXPIRE_TIME=86400
G
Google OAuth 配置
1. 创建 Google OAuth 应用
- 访问 Google Cloud Console
- 创建新项目或选择现有项目
- 启用 Google+ API
- 创建 OAuth 2.0 客户端 ID
- 配置授权重定向 URI:
https://yourdomain.com/api/auth/callback?provider=google
2. 环境变量配置
# Google OAuth 配置 GOOGLE_CLIENT_ID=your_google_client_id GOOGLE_CLIENT_SECRET=your_google_client_secret
🔌 API 参考
认证端点
GET
/api/auth/[provider]启动 OAuth 登录流程
支持的提供商
githubgooglemicrosoftgitee
查询参数
| 参数 | 类型 | 说明 |
|---|---|---|
| redirect | string | 登录成功后的重定向URL(可选) |
示例
// 基础登录 GET /api/auth/github // 带重定向的登录 GET /api/auth/github?redirect=/dashboard // JavaScript 中使用 window.location.href = '/api/auth/github?redirect=' + encodeURIComponent(window.location.pathname);
GET
/api/auth/me获取当前登录用户信息
请求头
Cookie: auth_token=your_jwt_token # 或者 Authorization: Bearer your_jwt_token
响应示例
{
"authenticated": true,
"user": {
"id": "123456",
"username": "johndoe",
"name": "John Doe",
"email": "john@example.com",
"avatar": "https://avatars.githubusercontent.com/u/123456",
"profileUrl": "https://github.com/johndoe",
"provider": "github",
"joinedAt": "2024-01-01T00:00:00.000Z",
"lastLoginAt": "2024-12-22T10:30:00.000Z"
},
"expiresAt": "2024-12-23T10:30:00.000Z"
}GET
/api/auth/sessions获取用户的所有活跃会话
响应示例
{
"sessions": [
{
"id": "session_123",
"deviceInfo": {
"browser": "Chrome",
"os": "macOS",
"device": "Desktop"
},
"ipAddress": "192.168.1.100",
"location": "北京, 中国",
"createdAt": "2024-12-22T10:30:00.000Z",
"lastActiveAt": "2024-12-22T15:45:00.000Z",
"isCurrent": true
}
],
"stats": {
"totalSessions": 3,
"activeSessions": 2,
"expiredSessions": 1
}
}🛡️ 中间件使用
路由保护
使用认证中间件保护需要登录的路由
// routes/protected-page.tsx
import { FreshContext } from "fresh";
import { getAuthContext } from "@utils/middleware.ts";
import type { AppUser } from "@utils/auth.ts";
interface ProtectedPageProps {
user: AppUser;
}
export const handler = {
async GET(ctx: FreshContext): Promise<Response> {
const req = ctx.req;
const authContext = await getAuthContext(req);
if (!authContext.isAuthenticated) {
// 未登录,重定向到登录页面
const loginUrl = `/api/auth/github?redirect=${
encodeURIComponent(req.url)
}`;
return new Response(null, {
status: 302,
headers: { "Location": loginUrl },
});
}
return new Response(null, { status: 200 });
},
};
export default function ProtectedPage({ data }: PageProps<ProtectedPageProps>) {
return (
<div>
<h1>欢迎, {data.user.name}!</h1>
<p>这是一个受保护的页面</p>
</div>
);
}API 路由保护
// routes/api/protected-endpoint.ts
import { FreshContext } from "fresh";
import { getAuthContext } from "@utils/middleware.ts";
export const handler = {
async GET(ctx: FreshContext): Promise<Response> {
const req = ctx.req;
const authContext = await getAuthContext(req);
if (!authContext.isAuthenticated) {
return new Response(
JSON.stringify({ error: "Authentication required" }),
{
status: 401,
headers: { "Content-Type": "application/json" }
}
);
}
// 处理已认证的请求
return new Response(
JSON.stringify({
message: "Hello, " + authContext.user?.name,
data: "sensitive data"
}),
{
status: 200,
headers: { "Content-Type": "application/json" }
}
);
},
};🔒 安全最佳实践
JWT 令牌安全
✅ 推荐做法
- • 使用强随机密钥(至少256位)
- • 设置合理的过期时间(24小时内)
- • 使用 HttpOnly Cookie 存储
- • 启用 SameSite 保护
- • 定期轮换密钥
❌ 避免做法
- • 在 localStorage 中存储令牌
- • 使用弱密钥或默认密钥
- • 设置过长的过期时间
- • 在 URL 中传递令牌
- • 忽略令牌验证
环境变量配置
# 生成强随机密钥 JWT_SECRET=$(openssl rand -base64 32) # 设置合理的过期时间(秒) SESSION_EXPIRE_TIME=86400 # 24小时 # 启用安全Cookie设置 SECURE_COOKIES=true SAMESITE_STRICT=true
HTTPS 和 Cookie 安全
Cookie 安全配置
// 安全的 Cookie 设置
const secureCookie = [
"auth_token=jwt_token_here",
"HttpOnly", // 防止 XSS 攻击
"Secure", // 仅在 HTTPS 下传输
"SameSite=Strict", // 防止 CSRF 攻击
"Max-Age=86400", // 24小时过期
"Path=/", // 全站有效
].join("; ");重要提醒
生产环境必须使用 HTTPS。在开发环境中,Secure 标志会阻止 Cookie 在 HTTP 下工作。
常见攻击防护
CSRF 防护
- • 使用 SameSite Cookie 属性
- • 验证 Referer 头
- • 实施 CSRF 令牌
- • 双重提交 Cookie
XSS 防护
- • 使用 HttpOnly Cookie
- • 输入验证和转义
- • 内容安全策略 (CSP)
- • 避免 innerHTML 使用
会话劫持防护
- • 强制 HTTPS 传输
- • 定期轮换会话ID
- • 监控异常登录
- • 实施会话超时
暴力破解防护
- • 实施速率限制
- • 账户锁定机制
- • 验证码保护
- • 监控失败尝试
🚀 部署指南
环境变量配置
必需的环境变量
# 基础配置 BASE_URL=https://yourdomain.com JWT_SECRET=your_super_secret_jwt_key_here SESSION_EXPIRE_TIME=86400 # GitHub OAuth GITHUB_CLIENT_ID=your_github_client_id GITHUB_CLIENT_SECRET=your_github_client_secret # Google OAuth GOOGLE_CLIENT_ID=your_google_client_id GOOGLE_CLIENT_SECRET=your_google_client_secret # Microsoft OAuth MICROSOFT_CLIENT_ID=your_microsoft_client_id MICROSOFT_CLIENT_SECRET=your_microsoft_client_secret # Gitee OAuth GITEE_CLIENT_ID=your_gitee_client_id GITEE_CLIENT_SECRET=your_gitee_client_secret
可选的环境变量
# 安全配置 SECURE_COOKIES=true SAMESITE_STRICT=true CORS_ORIGIN=https://yourdomain.com # 日志配置 LOG_LEVEL=info ENABLE_AUTH_LOGS=true # 会话配置 MAX_SESSIONS_PER_USER=10 SESSION_CLEANUP_INTERVAL=3600
Deno Deploy 部署
- 连接 GitHub 仓库
在 Deno Deploy 控制台中连接你的 GitHub 仓库
- 配置环境变量
在项目设置中添加所有必需的环境变量
- 设置自定义域名
配置你的域名并确保 HTTPS 证书正常工作
- 更新 OAuth 回调 URL
在各个 OAuth 提供商中更新回调 URL 为生产域名
部署检查清单
- □ 所有环境变量已配置
- □ OAuth 应用回调 URL 已更新
- □ HTTPS 证书正常工作
- □ 认证流程测试通过
- □ 会话管理功能正常
🔧 故障排除
Q: OAuth 登录失败,显示 'invalid_client' 错误
A: 检查 OAuth 应用的 Client ID 和 Client Secret 是否正确配置,确保回调 URL 与 OAuth 应用设置中的 URL 完全匹配。
Q: 用户登录后立即被重定向到登录页面
A: 可能是 JWT 密钥配置错误或 Cookie 设置问题。检查 JWT_SECRET 环境变量,确保在生产环境中启用了 HTTPS。
Q: 会话管理 API 返回 401 错误
A: 确保请求包含有效的认证 Cookie 或 Authorization 头,检查 JWT 令牌是否过期。
Q: 在开发环境中 Cookie 无法设置
A: 在开发环境中禁用 Secure Cookie 标志,或使用 HTTPS 进行本地开发。
Q: 多个会话之间出现冲突
A: 检查会话存储实现,确保会话 ID 的唯一性,考虑实施会话清理机制。
调试技巧
启用详细日志
# 在 .env 中添加 LOG_LEVEL=debug ENABLE_AUTH_LOGS=true
检查 JWT 令牌
// 在浏览器控制台中
document.cookie
.split(';')
.find(c => c.includes('auth_token'))