import Connect from 'connect'; import { ServerResponse } from 'node:http'; import https from 'https'; import { parse as parseCookie } from 'cookie'; import { sendReLogin } from '../SSE/server'; import casdoorServer from 'casdoor-nodejs-sdk'; import { ServerUrl, ClientId, SecretKey, Certificate, AppName, OrganizationName } from './config'; const sdk = new casdoorServer.SDK({ endpoint: ServerUrl, clientId: ClientId, clientSecret: SecretKey, certificate: Certificate, orgName: OrganizationName, appName: AppName }, { httpsAgent: new https.Agent({ rejectUnauthorized: false }) }) // 未授权响应 function resUnauthorized(res: ServerResponse, cookies?: Record) { res.statusCode = 401; // Unauthorized res.setHeader('Content-Type', 'text/plain') res.end('Unauthorized') if (cookies) { const session_id = cookies['session_id'] if (session_id) { // 重新登录 setTimeout(() => { sendReLogin(session_id); }, 3000); } } } // 处理登录请求 async function handleSignin(url: URL): Promise<{ access_token: string; refresh_token: string; } | undefined> { const code = url.searchParams.get('code'); const state = url.searchParams.get('state'); if (code && state) { const token = await sdk.getAuthToken(code); return token } return undefined } // 验证Token function verifyToken(token: string): boolean { try { sdk.parseJwtToken(token); return true; } catch (err) { console.error("token verify failed."); console.error(err); } return false; } // 刷新Token async function refreshToken(refresh_token: string) { const tokenGroup = await sdk.refreshToken(refresh_token).catch(err => { console.error("refresh token failed.") console.error(err) return undefined }) return tokenGroup; } export default async function AuthMid(req: Connect.IncomingMessage, res: ServerResponse, next: Connect.NextFunction) { const BaseUrl = process.env.BASE_URL if (req.url) { const url = new URL(req.url, "https://raspberrypi.dev"); // 请求保护资源,验证JWT if (!url.pathname.startsWith(BaseUrl + 'casdoor') && url.pathname.endsWith('.md')) { console.log("verify JWT") const cookieStr = req.headers.cookie if (!cookieStr) { resUnauthorized(res); return } else { const cookies = parseCookie(cookieStr); console.log(cookies) const token = cookies['token']; const refresh_token = cookies['refresh_token']; // 验证Token if (token && verifyToken(token)) { // 验证成功 await next(); return } // 验证刷新Token if (refresh_token && verifyToken(refresh_token)) { // 刷新Token const tokenGroup = await refreshToken(refresh_token); if (tokenGroup) { // 刷新成功,设置token res.setHeader('Set-Cookie', [ `token=${tokenGroup.access_token}; HttpOnly; Path=/; Max-Age=86400; SameSite=Strict`, `refresh_token=${tokenGroup.refresh_token}; HttpOnly; Path=/; SameSite=Strict` ]); await next(); return } } resUnauthorized(res, cookies); return } } // 处理登录查询 if (url.pathname.startsWith(BaseUrl + 'api/islogin')) { const cookieStr = req.headers.cookie if (cookieStr) { const cookies = parseCookie(cookieStr); const token = cookies['token']; const refresh_token = cookies['refresh_token']; // 验证Token if (token && verifyToken(token)) { // 验证成功 res.statusCode = 200; res.setHeader('Content-Type', 'text/plain') res.end(token) return } // 验证刷新Token if (refresh_token && verifyToken(refresh_token)) { // 刷新Token const tokenGroup = await refreshToken(refresh_token); if (tokenGroup) { // 刷新成功,设置token res.setHeader('Set-Cookie', [ `token=${tokenGroup.access_token}; HttpOnly; Path=/; Max-Age=86400; SameSite=Strict`, `refresh_token=${tokenGroup.refresh_token}; HttpOnly; Path=/; SameSite=Strict` ]); res.statusCode = 200; res.setHeader('Content-Type', 'text/plain') res.end(token) return } } } resUnauthorized(res); return } // 处理登录请求 if (url.pathname.startsWith(BaseUrl + 'api/signin')) { const signinToken = await handleSignin(url).catch((err) => { console.log("handleSignin: ", err) }); console.log("signinToken: ", signinToken) if (signinToken) { res.setHeader('Set-Cookie', [ `token=${signinToken.access_token}; HttpOnly; Path=/; Max-Age=86400; SameSite=Strict`, `refresh_token=${signinToken.refresh_token}; HttpOnly; Path=/; SameSite=Strict` ]) res.statusCode = 200; res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(signinToken)) return } } // 处理登录请求 if (url.pathname.startsWith(BaseUrl + 'api/exit')) { console.log("exit") // 清除token res.setHeader('Set-Cookie', [ `token=; HttpOnly; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict`, `refresh_token=; HttpOnly; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict` ]) res.statusCode = 200; res.setHeader('Content-Type', 'text/plain') res.end("Exit successful.") return } } // 继续执行下一个中间件 await next(); }