/** * WebVPN 会话 Cookie:调用 ic-ctbu-backend-py /webvpnlogin,并可 Redis 缓存。 */ const axios = require('axios') const config = require('../../config.json') const db = require('../../plugin/DataBase/db') const Redis = require('../../plugin/DataBase/Redis') const CACHE_PREFIX = 'webvpn_cookie:' const CACHE_TTL_SEC = 25 * 60 function webvpnLoginBaseUrl() { const u = config.webvpnLoginBaseUrl || config.url3 return (u && String(u).replace(/\/$/, '')) || '' } function isProbablyVpnLoginHtml(body) { if (typeof body !== 'string') return false return ( body.includes('lyuapServer') || body.includes('ivpn') || body.includes('统一认证') || body.includes('rump_frontend/login') ) } async function fetchWebVpnCookieFromPy(username, password) { const base = webvpnLoginBaseUrl() if (!base) { throw new Error('未配置 webvpnLoginBaseUrl') } const url = `${base}/webvpnlogin` const res = await axios.post( url, { username, password }, { timeout: 120000, proxy: false, validateStatus: () => true } ) const data = res.data if (!data || data.code !== 0 || !data.webvpn_cookie) { throw new Error(data?.msg || 'WebVPN 登录失败') } return String(data.webvpn_cookie) } async function getJwPasswordForUser(uuid, jwUsername) { const rows = await db.query( 'SELECT password FROM jw_account WHERE create_user = ? AND username = ? AND state IN (0, 1)', [uuid, jwUsername] ) if (!rows || rows.length !== 1 || !rows[0].password) { throw new Error('未绑定教务账号或账号不可用,请先绑定教务账号') } return rows[0].password } /** * @param {string} createUserUuid * @param {string} jwUsername 教务登录名 * @param {{ skipCache?: boolean }} [opts] */ async function getWebVpnCookieHeader(createUserUuid, jwUsername, opts = {}) { const skipCache = opts.skipCache === true const key = `${CACHE_PREFIX}${createUserUuid}:${jwUsername}` if (!skipCache) { const cached = await Redis.get(key) if (cached) return cached } const pwd = await getJwPasswordForUser(createUserUuid, jwUsername) const cookie = await fetchWebVpnCookieFromPy(jwUsername, pwd) await Redis.set(key, cookie, { EX: CACHE_TTL_SEC }) return cookie } async function invalidateWebVpnCookie(createUserUuid, jwUsername) { const key = `${CACHE_PREFIX}${createUserUuid}:${jwUsername}` await Redis.del(key) } module.exports = { webvpnLoginBaseUrl, isProbablyVpnLoginHtml, fetchWebVpnCookieFromPy, getWebVpnCookieHeader, invalidateWebVpnCookie, CACHE_TTL_SEC }