49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
import { NextResponse } from 'next/server'
|
|
import { cookies } from 'next/headers'
|
|
import { signSharedJwt, sharedCookieConfig } from '@/lib/jwt'
|
|
import { ldapAuth, isLldapAdmin } from '@/lib/ldap'
|
|
import { writeAuditLog } from '@/lib/audit'
|
|
import { syncUserToAllSites } from '@/lib/sync-user'
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const { username, password } = await request.json()
|
|
if (!username || !password) {
|
|
return NextResponse.json({ error: '请输入用户名和密码' }, { status: 400 })
|
|
}
|
|
|
|
const result = await ldapAuth(username, password)
|
|
if (!result.success) {
|
|
if (result.unreachable) {
|
|
return NextResponse.json({ error: '认证服务暂时不可用,请稍后再试' }, { status: 503 })
|
|
}
|
|
return NextResponse.json({ error: '用户名或密码错误' }, { status: 401 })
|
|
}
|
|
|
|
const token = signSharedJwt({ username: result.username!, displayName: result.displayName! })
|
|
const cfg = sharedCookieConfig()
|
|
const cookieStore = await cookies()
|
|
cookieStore.set(cfg.name, token, cfg)
|
|
|
|
// 审计日志
|
|
try {
|
|
writeAuditLog({
|
|
username: result.username!,
|
|
action: 'login',
|
|
details: { method: 'ldap', displayName: result.displayName },
|
|
ipAddress: request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown',
|
|
})
|
|
} catch { /* 审计日志失败不影响登录 */ }
|
|
|
|
// 跨站点角色同步(不阻塞响应)
|
|
const role = (await isLldapAdmin(result.username!)) ? 'admin' : 'viewer'
|
|
syncUserToAllSites(result.username!, result.displayName!, role).catch(() => {})
|
|
|
|
return NextResponse.json({
|
|
user: { username: result.username, displayName: result.displayName },
|
|
})
|
|
} catch {
|
|
return NextResponse.json({ error: '登录失败' }, { status: 500 })
|
|
}
|
|
}
|