diff --git a/src/express.d.ts b/src/express.d.ts index eb523dff2..846c5b9b2 100644 --- a/src/express.d.ts +++ b/src/express.d.ts @@ -4,6 +4,10 @@ export declare module "express-serve-static-core" { interface Request { session: Session & { loggedIn: boolean; + lastAuthState: { + totpEnabled: boolean; + ssoEnabled: boolean; + }; }; headers: { "x-local-date"?: string; diff --git a/src/routes/login.ts b/src/routes/login.ts index 52dfb0b68..c6aacfa9f 100644 --- a/src/routes/login.ts +++ b/src/routes/login.ts @@ -88,6 +88,12 @@ function login(req: Request, res: Response) { req.session.cookie.maxAge = undefined; } + // 记录当前的认证状态 + req.session.lastAuthState = { + totpEnabled: totp.isTotpEnabled(), + ssoEnabled: open_id.isOpenIDEnabled() + }; + req.session.loggedIn = true; res.redirect('.'); }); diff --git a/src/routes/session_parser.ts b/src/routes/session_parser.ts index 89df0e037..9d52580d2 100644 --- a/src/routes/session_parser.ts +++ b/src/routes/session_parser.ts @@ -3,6 +3,10 @@ import sessionFileStore from "session-file-store"; import sessionSecret from "../services/session_secret.js"; import dataDir from "../services/data_dir.js"; import config from "../services/config.js"; +import totp from "../services/totp.js"; +import open_id from "../services/open_id.js"; +import type { Request, Response, NextFunction } from "express"; + const FileStore = sessionFileStore(session); const sessionParser = session({ @@ -21,4 +25,44 @@ const sessionParser = session({ }) }); -export default sessionParser; +// 创建一个检查认证状态的中间件 +const checkAuthState = (req: Request, res: Response, next: NextFunction) => { + // 如果用户未登录或者是登录页面,直接继续 + if (!req.session.loggedIn || req.path === '/login') { + return next(); + } + + const currentTotpStatus = totp.isTotpEnabled(); + const currentSsoStatus = open_id.isOpenIDEnabled(); + + // 从 session 中获取上次登录时的认证状态 + const lastAuthState = req.session.lastAuthState || { + totpEnabled: false, + ssoEnabled: false + }; + + // 检查认证状态是否发生变化 + if (lastAuthState.totpEnabled !== currentTotpStatus || + lastAuthState.ssoEnabled !== currentSsoStatus) { + // 如果认证状态发生变化,先销毁当前 session + req.session.destroy((err) => { + if (err) { + console.error('Error destroying session:', err); + } + // 清除 cookie + res.clearCookie('trilium.sid'); + // 重定向到登录页面 + res.redirect('/login'); + }); + return; + } + + next(); +}; + +// 导出一个组合的中间件 +export default function (req: Request, res: Response, next: NextFunction) { + sessionParser(req, res, () => { + checkAuthState(req, res, next); + }); +}