77 行
3.0 KiB
TypeScript
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();
|
|
});
|
|
});
|
|
});
|