feie9456 747dcd359a 家庭守护圈:多人加入、角色权限、24 小时邀请链接、旧设备绑定自动兼容。
家庭动态:老人/家属发言、三种可见范围,家庭内部内容不会播给老人。
共同照护:家庭备忘录、任务创建、认领、完成与交接记录。
用药闭环:计划、未来 7 天提醒实例、确认服用、延后、异常反馈。
风险闭环:红橙黄蓝分级、30 分钟去重、推送、认领、处理与误报记录。
报平安:家属发起、老人语音回应、状态同步。
Web 导航升级为守护、家庭、照护、陪伴、我的。
设备接口已升级为设备令牌认证,UUID 不再单独承担认证。
2026-07-18 19:59:20 +08:00

30 lines
1.3 KiB
TypeScript

import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
import { prisma } from "@/lib/prisma";
export function hashDeviceToken(token: string) {
return createHash("sha256").update(token).digest("hex");
}
export function createDeviceToken() {
return randomBytes(32).toString("base64url");
}
export function readDeviceToken(request: Request) {
const authorization = request.headers.get("authorization") || "";
return authorization.startsWith("Bearer ")
? authorization.slice(7).trim()
: request.headers.get("x-device-token")?.trim() || "";
}
export async function requireDeviceAuth(request: Request, deviceUuid: string) {
const token = readDeviceToken(request);
if (!token) throw new Error("设备认证信息缺失,请重新注册设备。");
const device = await prisma.elderDevice.findUnique({ where: { deviceUuid }, select: { id: true, deviceUuid: true, deviceTokenHash: true } });
if (!device?.deviceTokenHash) throw new Error("设备尚未完成安全注册。");
const actual = Buffer.from(hashDeviceToken(token));
const expected = Buffer.from(device.deviceTokenHash);
if (actual.length !== expected.length || !timingSafeEqual(actual, expected)) throw new Error("设备认证失败,请重新注册设备。");
return device;
}