鉴权
本项目的接口均需要鉴权,鉴权方式为在请求头中添加 token 字段,值为登录后获取的 token。
获取方法主要提供以下几种
通过脚本获取
import axios from "axios";
import crypto from "crypto";
import { CookieJar } from "tough-cookie";
import { wrapper } from "axios-cookiejar-support";
const SSO_URL = "https://sso.fzu.edu.cn/login";
const AUTH_URL =
"https://sso.fzu.edu.cn/oauth2.0/authorize?response_type=code&client_id=wlwxt&redirect_uri=http://aiot.fzu.edu.cn/api/admin/sso/getIbsToken";
const USER_AGENT =
"Mozilla/5.0 (iPad; CPU OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 appId/cn.edu.fzu.fdxypa appScheme/kysk-fdxy-app hengfeng/fdxyappzs appType/2 ruijie-facecamera";
/* -------- utils -------- */
function extractKV(rawText, key) {
const re = new RegExp(`${key}=([^;&]+)`);
const m = rawText.match(re);
if (!m) throw new Error(`未找到键: ${key}`);
return m[1];
}
function encryptPassword(rawPassword, keyBase64) {
const key = Buffer.from(keyBase64, "base64");
const cipher = crypto.createCipheriv("aes-128-ecb", key, null);
cipher.setAutoPadding(true); // PKCS#7
const encrypted = Buffer.concat([
cipher.update(rawPassword, "utf8"),
cipher.final(),
]);
return encrypted.toString("base64");
}
/* -------- main function -------- */
export async function getLearningCenterToken(username, password) {
if (!username || !password) throw new Error("账号密码不能为空");
const jar = new CookieJar();
const client = wrapper(
axios.create({
jar,
withCredentials: true,
headers: { "User-Agent": USER_AGENT },
maxRedirects: 10,
validateStatus: (s) => s >= 200 && s < 400,
})
);
/* 1. GET 登录页 */
const pageResp = await client.get(SSO_URL);
const html = pageResp.data;
const cryptoMatch = html.match(/"login-croypto">(.*?)</);
const executionMatch = html.match(/"login-page-flowkey">(.*?)</);
if (!cryptoMatch || !executionMatch) {
throw new Error("无法提取 crypto / execution");
}
const cryptoKey = cryptoMatch[1];
const execution = executionMatch[1];
const setCookie = pageResp.headers["set-cookie"]?.join("; ") ?? "";
const sessionVal = extractKV(setCookie, "SESSION");
/* 2. POST 登录 */
const form = new URLSearchParams({
username,
type: "UsernamePassword",
_eventId: "submit",
geolocation: "",
execution,
captcha_code: "",
croypto: cryptoKey,
password: encryptPassword(password, cryptoKey),
captcha_payload: encryptPassword("{}", cryptoKey),
});
await client.post(SSO_URL, form.toString(), {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Cookie: `SESSION=${sessionVal}`,
},
});
/* 3. 拿 SOURCEID_TGC */
const cookies = await jar.getCookies(SSO_URL);
const tgc = cookies.find((c) => c.key === "SOURCEID_TGC");
if (!tgc) throw new Error("学号或密码错误");
/* 4. OAuth 跳转拿 token */
const authResp = await client.get(AUTH_URL, {
headers: {
Cookie: `SOURCEID_TGC=${tgc.value}`,
},
});
const finalUrl =
authResp?.request?.res?.responseUrl ?? authResp.config.url;
if (!finalUrl.includes("token=")) {
throw new Error("未在最终 URL 中找到 token");
}
return extractKV(finalUrl, "token");
}
直接登录
自行访问 https://aiot.fzu.edu.cn/api/ibs ,登录后的网址会携带 token,可以从中提取。