文件
OmniCard/backend/test/modules/card/privacy.test.ts

77 行
3.0 KiB
TypeScript

import {
CardPrivacyPasswordService,
hashPrivacyPassword,
verifyPrivacyPassword,
generatePrivacyAccessToken,
verifyPrivacyAccessToken,
} from '../../../src/modules/card/service/privacy';
describe('Point 59 (P2): 移动微官网名片私密保护模式与访问口令鉴权', () => {
let service: CardPrivacyPasswordService;
const mockCardId = 601;
const rawPassword = 'Vip-Secret-Pass-2026';
beforeEach(() => {
service = new CardPrivacyPasswordService();
});
describe('1. 密码加盐哈希与校验 (hashPrivacyPassword & verifyPrivacyPassword)', () => {
it('应使用 SHA-256 加盐算法生成密码哈希,不存明文', () => {
const hashed = hashPrivacyPassword(rawPassword);
expect(hashed).toContain(':');
expect(hashed).not.toBe(rawPassword);
// 正确口令校验成功
expect(verifyPrivacyPassword(rawPassword, hashed)).toBe(true);
// 错误口令校验失败
expect(verifyPrivacyPassword('wrong-password', hashed)).toBe(false);
});
it('空密码或无效哈希时应安全返回 false', () => {
expect(verifyPrivacyPassword('', 'salt:hash')).toBe(false);
expect(verifyPrivacyPassword('pass', '')).toBe(false);
});
});
describe('2. 私密解锁授权凭据 (Privacy Access Token)', () => {
it('口令验证成功后生成包含时钟与签名的临时访问 Token', () => {
const token = generatePrivacyAccessToken(mockCardId, 'sys-secret-key', 3600);
expect(token).toBeDefined();
const verifyRes = verifyPrivacyAccessToken(mockCardId, token, 'sys-secret-key');
expect(verifyRes.valid).toBe(true);
expect(verifyRes.cardId).toBe(mockCardId);
});
it('Token 跨名片使用时应被严密拦截', () => {
const token = generatePrivacyAccessToken(mockCardId, 'sys-secret-key');
// 尝试用来解锁 602 名片
const verifyRes = verifyPrivacyAccessToken(602, token, 'sys-secret-key');
expect(verifyRes.valid).toBe(false);
expect(verifyRes.reason).toMatch(/不匹配|mismatch/i);
});
it('伪造或过期的 Token 应被坚决拒绝', () => {
const expiredToken = generatePrivacyAccessToken(mockCardId, 'sys-secret-key', -10); // 已过期
const res = verifyPrivacyAccessToken(mockCardId, expiredToken, 'sys-secret-key');
expect(res.valid).toBe(false);
expect(res.reason).toMatch(/过期|expired/i);
});
});
describe('3. CardPrivacyPasswordService 解锁与脱敏输出', () => {
it('未解锁前返回脱敏联系方式,验证口令后颁发解锁凭据', async () => {
const hashed = hashPrivacyPassword(rawPassword);
// 1. 验证错误口令
const failUnlock = await service.unlockCard(mockCardId, 'wrong', hashed);
expect(failUnlock.success).toBe(false);
// 2. 验证正确口令
const successUnlock = await service.unlockCard(mockCardId, rawPassword, hashed);
expect(successUnlock.success).toBe(true);
expect(successUnlock.accessToken).toBeDefined();
});
});
});