- access token 是 15 分钟的 JWT,走 Authorization: Bearer;refresh token 7 天,每次换都轮换 - 退出登录、改密码、禁用账号仍然立刻生效:每个请求核对 Redis 会话和库里新加的 user.token_version - 在服务器后台改密码 / 禁用,机房那边登着的也会一起下线(原来两边 Redis 分开,管不到) - WebSocket 握手借子协议带 token;JWT 密钥存在本站 Redis,部署不用加配置 - 去掉 COOKIE_SECURE;上线后所有人要重新登录一次 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4be569d978
commit
793848b06f
31 files changed
+4639
-333
No files matched your search
+12
-4
@@ -1,7 +1,9 @@
|
||||
import { Hono } from "hono"
|
||||
import { basename, resolve } from "node:path"
|
||||
|
||||
import { getRequestSessionUser, readRequestSessionToken } from "./auth/session"
|
||||
import { WS_AUTH_PROTOCOL } from "@oj2/contract"
|
||||
|
||||
import { authenticateWebSocket, loadJwtSecret } from "./auth/session"
|
||||
import { config } from "./config"
|
||||
import { adminRoutes } from "./routes/admin"
|
||||
import { authRoutes } from "./routes/auth"
|
||||
@@ -88,6 +90,8 @@ async function serveUpload(pathname: string, prefix: string, directory: string)
|
||||
return null
|
||||
}
|
||||
|
||||
await loadJwtSecret()
|
||||
|
||||
const server = Bun.serve<SubmissionSocketData>({
|
||||
port: config.port,
|
||||
// Bun 默认 10 秒没有字节往来就掐连接,而且不报任何错。AI 的 SSE 两条路都会静默
|
||||
@@ -126,8 +130,9 @@ const server = Bun.serve<SubmissionSocketData>({
|
||||
if (!isAllowedWebSocketOrigin(request.headers.get("origin"), url)) {
|
||||
return new Response("Forbidden", { status: 403 })
|
||||
}
|
||||
const user = await getRequestSessionUser(request)
|
||||
if (!user) return new Response("Unauthorized", { status: 401 })
|
||||
const session = await authenticateWebSocket(request)
|
||||
if (!session) return new Response("Unauthorized", { status: 401 })
|
||||
const { user } = session
|
||||
const kind =
|
||||
url.pathname === "/ws/config"
|
||||
? "config"
|
||||
@@ -136,10 +141,13 @@ const server = Bun.serve<SubmissionSocketData>({
|
||||
: "submissions"
|
||||
if (
|
||||
bunServer.upgrade(request, {
|
||||
// 前端是借子协议带 token 来的,不回一个它传过的子协议 Chrome 就判握手失败
|
||||
headers: { "Sec-WebSocket-Protocol": WS_AUTH_PROTOCOL },
|
||||
data: {
|
||||
userId: user.id,
|
||||
kind,
|
||||
token: readRequestSessionToken(request),
|
||||
sid: session.sid,
|
||||
tokenVersion: session.tokenVersion,
|
||||
username: user.username,
|
||||
adminType: user.adminType,
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user