xiaohongshufabu/web/src/auth.js
2026-07-22 10:07:46 +08:00

118 lines
3.2 KiB
JavaScript

const STORAGE_KEY = "taiyi1224";
const MACHINE_KEY = "xhsp_machine_code";
export function getStoredAuth() {
try {
const raw = localStorage.getItem(STORAGE_KEY);
return raw ? JSON.parse(raw) : null;
} catch {
return null;
}
}
export function saveStoredAuth(data) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
window.dispatchEvent(new CustomEvent("license-auth-changed", { detail: data }));
}
export function clearStoredAuth() {
localStorage.removeItem(STORAGE_KEY);
window.dispatchEvent(new CustomEvent("license-auth-changed", { detail: null }));
}
export function getAccessToken() {
return getStoredAuth()?.token || "";
}
async function sha256Hex(input) {
const bytes = new TextEncoder().encode(input);
const buffer = await crypto.subtle.digest("SHA-256", bytes);
return Array.from(new Uint8Array(buffer)).map((item) => item.toString(16).padStart(2, "0")).join("");
}
export async function getMachineCode() {
const cached = localStorage.getItem(MACHINE_KEY);
if (cached) return cached;
const fingerprint = [
navigator.userAgent,
navigator.language,
navigator.platform,
screen.width,
screen.height,
new Date().getTimezoneOffset(),
].join("|");
const code = (await sha256Hex(fingerprint)).slice(0, 32).toUpperCase();
localStorage.setItem(MACHINE_KEY, code);
return code;
}
export async function verifyLicenseKey(licenseKey) {
const machineCode = await getMachineCode();
const response = await fetch("/api/license/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ licenseKey, machineCode }),
});
const data = await response.json().catch(() => ({ success: false, message: "授权服务返回异常" }));
if (!response.ok || data.success === false) {
throw new Error(data.message || "卡密验证失败");
}
const auth = {
token: data.token,
auth: data.auth,
recheckIntervalMs: data.recheckIntervalMs,
};
saveStoredAuth(auth);
return auth;
}
export async function refreshLicenseStatus() {
const token = getAccessToken();
if (!token) return null;
const response = await fetch("/api/license/status", {
headers: { Authorization: `Bearer ${token}` },
});
const data = await response.json().catch(() => ({ success: false, message: "授权状态检查失败" }));
if (!response.ok || data.success === false) {
clearStoredAuth();
throw new Error(data.message || "授权已失效");
}
const auth = {
token: data.token || token,
auth: data.auth,
recheckIntervalMs: data.recheckIntervalMs,
};
saveStoredAuth(auth);
return auth;
}
export async function unbindCurrentLicense() {
const token = getAccessToken();
if (!token) {
throw new Error("当前没有有效授权");
}
const response = await fetch("/api/license/unbind", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
const data = await response.json().catch(() => ({ success: false, message: "解绑服务返回异常" }));
if (!response.ok || data.success === false) {
throw new Error(data.message || "解绑失败");
}
clearStoredAuth();
return data;
}