65 lines
2.0 KiB
Dart
65 lines
2.0 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:qiangbao_accounting/utils/crypto.dart';
|
|
import 'package:qiangbao_accounting/utils/jwt_util.dart';
|
|
|
|
/// 构造一个只含 payload 的假 JWT(本地 exp 判断不校验签名)
|
|
String fakeJwt({DateTime? expiredAt, bool withExp = true}) {
|
|
String seg(Map<String, dynamic> m) =>
|
|
base64Url.encode(utf8.encode(jsonEncode(m))).replaceAll('=', '');
|
|
final header = seg({'alg': 'HS512'});
|
|
final payload = seg({
|
|
'sub': 'tester',
|
|
if (withExp)
|
|
'exp': (expiredAt ?? DateTime.now().add(const Duration(hours: 1)))
|
|
.millisecondsSinceEpoch ~/
|
|
1000,
|
|
});
|
|
return '$header.$payload.signature';
|
|
}
|
|
|
|
void main() {
|
|
test('crypto encrypt/decrypt roundtrip 与 uniApp 端算法一致', () {
|
|
const password = 'abc12345';
|
|
final encrypted = encryptPassword(password);
|
|
expect(encrypted, isNotEmpty);
|
|
expect(encrypted, isNot(password));
|
|
expect(decryptPassword(encrypted), password);
|
|
});
|
|
|
|
group('JWT 过期判断', () {
|
|
test('未来的 exp 视为未过期', () {
|
|
expect(
|
|
isJwtExpired(fakeJwt(expiredAt: DateTime.now().add(const Duration(hours: 1)))),
|
|
isFalse,
|
|
);
|
|
});
|
|
|
|
test('过去的 exp 视为已过期', () {
|
|
expect(
|
|
isJwtExpired(fakeJwt(expiredAt: DateTime.now().subtract(const Duration(hours: 1)))),
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
test('即将过期(落在 30 秒余量内)视为已过期', () {
|
|
expect(
|
|
isJwtExpired(fakeJwt(expiredAt: DateTime.now().add(const Duration(seconds: 5)))),
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
test('无 exp 字段不做本地判断,避免误判', () {
|
|
expect(isJwtExpired(fakeJwt(withExp: false)), isFalse);
|
|
});
|
|
|
|
test('非 JWT 格式不做本地判断;空 token 视为无效', () {
|
|
expect(isJwtExpired('not-a-jwt'), isFalse);
|
|
expect(isJwtExpired(''), isTrue);
|
|
expect(isJwtExpired(null), isTrue);
|
|
});
|
|
});
|
|
}
|