fix:参考金值,研听,研值工程通用通用工程公共能力,重点对比网络请求、登录认证、状态管理、本地存储、WebView、推送、版本更新、一键登录、主题/UI 等模块,确定后续统一整改方案
This commit is contained in:
1 parent
6997a65c96
commit
d364c6d908
46 files changed
+2060
-395
No files matched your search
@@ -1,6 +1,9 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jinzhi_flutter_app/common/storage/secure_identity_storage.dart';
|
||||
import 'package:jinzhi_flutter_app/common/storage/storage_keys.dart';
|
||||
import 'package:jinzhi_flutter_app/common/storage/preferences_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
void main() {
|
||||
@@ -14,7 +17,10 @@ void main() {
|
||||
});
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final secure = _MemorySecureStorage();
|
||||
final storage = SecureIdentityStorage(preferences, secureStorage: secure);
|
||||
final storage = SecureIdentityStorage(
|
||||
PreferencesStorage(preferences),
|
||||
secureStorage: secure,
|
||||
);
|
||||
|
||||
expect(await storage.restoreAccessToken(), 'legacy');
|
||||
expect(await secure.read('access_token'), 'legacy');
|
||||
@@ -24,17 +30,109 @@ void main() {
|
||||
);
|
||||
|
||||
test(
|
||||
'migrates the previous secure jwt key when no current token exists',
|
||||
'rejects an orphaned Keychain token when the install marker is absent',
|
||||
() async {
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final secure = _MemorySecureStorage({'jwt_token': 'secure-legacy'});
|
||||
final storage = SecureIdentityStorage(preferences, secureStorage: secure);
|
||||
final storage = SecureIdentityStorage(
|
||||
PreferencesStorage(preferences),
|
||||
secureStorage: secure,
|
||||
);
|
||||
|
||||
expect(await storage.restoreAccessToken(), 'secure-legacy');
|
||||
expect(await secure.read('access_token'), 'secure-legacy');
|
||||
expect(await storage.restoreAccessToken(), isNull);
|
||||
expect(await secure.read('access_token'), isNull);
|
||||
expect(await secure.read('jwt_token'), isNull);
|
||||
},
|
||||
);
|
||||
|
||||
test('restores a secure token only with the installation marker', () async {
|
||||
SharedPreferences.setMockInitialValues({storageAuthSessionActive: true});
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final secure = _MemorySecureStorage({secureAccessToken: 'active'});
|
||||
final storage = SecureIdentityStorage(
|
||||
PreferencesStorage(preferences),
|
||||
secureStorage: secure,
|
||||
);
|
||||
|
||||
expect(await storage.restoreAccessToken(), 'active');
|
||||
});
|
||||
|
||||
test('logout clears session secrets but preserves device identity', () async {
|
||||
SharedPreferences.setMockInitialValues({storageAuthSessionActive: true});
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final secure = _MemorySecureStorage({
|
||||
secureAccessToken: 'access',
|
||||
secureMallCredential: 'mall',
|
||||
secureRefreshToken: 'refresh',
|
||||
secureBiometricCredential: 'biometric',
|
||||
secureDeviceId: 'device',
|
||||
});
|
||||
final storage = SecureIdentityStorage(
|
||||
PreferencesStorage(preferences),
|
||||
secureStorage: secure,
|
||||
);
|
||||
|
||||
await storage.clearSessionCredentials();
|
||||
|
||||
expect(await secure.read(secureAccessToken), isNull);
|
||||
expect(await secure.read(secureMallCredential), isNull);
|
||||
expect(await secure.read(secureRefreshToken), isNull);
|
||||
expect(await secure.read(secureBiometricCredential), 'biometric');
|
||||
expect(await secure.read(secureDeviceId), 'device');
|
||||
|
||||
await storage.clearAccountCredentials();
|
||||
expect(await secure.read(secureBiometricCredential), isNull);
|
||||
expect(await secure.read(secureDeviceId), 'device');
|
||||
});
|
||||
|
||||
test(
|
||||
'serializes restore with logout so an old token cannot revive',
|
||||
() async {
|
||||
SharedPreferences.setMockInitialValues({storageAuthSessionActive: true});
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final secure = _BlockingReadSecureStorage({
|
||||
secureAccessToken: 'old-token',
|
||||
});
|
||||
final session = AuthSessionStorage(
|
||||
SecureIdentityStorage(
|
||||
PreferencesStorage(preferences),
|
||||
secureStorage: secure,
|
||||
),
|
||||
);
|
||||
|
||||
final restoring = session.restore();
|
||||
await secure.readStarted.future;
|
||||
final clearing = session.clear();
|
||||
secure.releaseRead.complete();
|
||||
|
||||
expect(await restoring, 'old-token');
|
||||
await clearing;
|
||||
expect(session.accessToken, isNull);
|
||||
expect(await secure.read(secureAccessToken), isNull);
|
||||
},
|
||||
);
|
||||
|
||||
test('serializes restore with login so the new token wins', () async {
|
||||
SharedPreferences.setMockInitialValues({storageAuthSessionActive: true});
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final secure = _BlockingReadSecureStorage({secureAccessToken: 'old-token'});
|
||||
final session = AuthSessionStorage(
|
||||
SecureIdentityStorage(
|
||||
PreferencesStorage(preferences),
|
||||
secureStorage: secure,
|
||||
),
|
||||
);
|
||||
|
||||
final restoring = session.restore();
|
||||
await secure.readStarted.future;
|
||||
final saving = session.save('new-token');
|
||||
secure.releaseRead.complete();
|
||||
|
||||
expect(await restoring, 'old-token');
|
||||
await saving;
|
||||
expect(session.accessToken, 'new-token');
|
||||
expect(await secure.read(secureAccessToken), 'new-token');
|
||||
});
|
||||
}
|
||||
|
||||
class _MemorySecureStorage implements SecureKeyValueStorage {
|
||||
@@ -54,3 +152,21 @@ class _MemorySecureStorage implements SecureKeyValueStorage {
|
||||
_values[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
class _BlockingReadSecureStorage extends _MemorySecureStorage {
|
||||
_BlockingReadSecureStorage(super.initial);
|
||||
|
||||
final readStarted = Completer<void>();
|
||||
final releaseRead = Completer<void>();
|
||||
var _blocked = false;
|
||||
|
||||
@override
|
||||
Future<String?> read(String key) async {
|
||||
if (key == secureAccessToken && !_blocked) {
|
||||
_blocked = true;
|
||||
readStarted.complete();
|
||||
await releaseRead.future;
|
||||
}
|
||||
return super.read(key);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user