Flutter 安全存储平台异常
Flutter Secure Storage Platform Exception
我正在使用 flutter 安全存储 (^5.0.2) 来保存令牌,但是在模拟器上调用 storage.write() 时出现以下错误(我正在使用 Pixel 5 API 30) 而当我在我的物理设备 (Honor 8x) 上使用它时它运行良好:
PlatformException (PlatformException(Exception encountered, write, java.lang.NullPointerException: Attempt to invoke interface method 'byte[] com.it_nomads.fluttersecurestorage.ciphers.StorageCipher.encrypt(byte[])' on a null object reference
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.write(FlutterSecureStoragePlugin.java:202)
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access0(FlutterSecureStoragePlugin.java:37)
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:289)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)
, null))
这是调试的输出:
W/KeyStore( 2975): KeyStore exception
W/KeyStore( 2975): android.os.ServiceSpecificException: (code 7)
W/KeyStore( 2975): at android.os.Parcel.createExceptionOrNull(Parcel.java:2387)
W/KeyStore( 2975): at android.os.Parcel.createException(Parcel.java:2357)
W/KeyStore( 2975): at android.os.Parcel.readException(Parcel.java:2340)
W/KeyStore( 2975): at android.os.Parcel.readException(Parcel.java:2282)
W/KeyStore( 2975): at android.security.keystore.IKeystoreService$Stub$Proxy.get(IKeystoreService.java:988)
W/KeyStore( 2975): at android.security.KeyStore.get(KeyStore.java:233)
W/KeyStore( 2975): at android.security.KeyStore.get(KeyStore.java:222)
W/KeyStore( 2975): at android.security.keystore.AndroidKeyStoreSpi.engineGetCertificate(AndroidKeyStoreSpi.java:165)
W/KeyStore( 2975): at java.security.KeyStore.getCertificate(KeyStore.java:1120)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.getPublicKey(RSACipher18Implementation.java:90)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.wrap(RSACipher18Implementation.java:39)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:52)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.ensureInitialized(FlutterSecureStoragePlugin.java:95)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access0(FlutterSecureStoragePlugin.java:37)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:284)
W/KeyStore( 2975): at android.os.Handler.handleCallback(Handler.java:938)
W/KeyStore( 2975): at android.os.Handler.dispatchMessage(Handler.java:99)
W/KeyStore( 2975): at android.os.Looper.loop(Looper.java:223)
W/KeyStore( 2975): at android.os.HandlerThread.run(HandlerThread.java:67)
E/FlutterSecureStoragePl( 2975): StorageCipher initialization failed
E/FlutterSecureStoragePl( 2975): java.lang.Exception: No certificate found under alias: com.example.applielikya.FlutterSecureStoragePluginKey
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.getPublicKey(RSACipher18Implementation.java:92)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.wrap(RSACipher18Implementation.java:39)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:52)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.ensureInitialized(FlutterSecureStoragePlugin.java:95)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access0(FlutterSecureStoragePlugin.java:37)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:284)
E/FlutterSecureStoragePl( 2975): at android.os.Handler.handleCallback(Handler.java:938)
E/FlutterSecureStoragePl( 2975): at android.os.Handler.dispatchMessage(Handler.java:99)
E/FlutterSecureStoragePl( 2975): at android.os.Looper.loop(Looper.java:223)
E/FlutterSecureStoragePl( 2975): at android.os.HandlerThread.run(HandlerThread.java:67)
我不知道它是否相关,但我的代码中有 min Sdk 19,因为一些包需要这个版本。
我需要这个来启动我的物理设备和 Vscode 上的模拟器,在我的应用程序中使用两个不同的帐户(一个管理员和一个用户)来检查通知从一个到另一个的传输,如果另一个实现这一目标的方法存在,我也会知道。
这是代码:
import 'package:applielikya/models/login_response.dart';
import 'package:applielikya/models/user.dart';
import 'package:applielikya/services/auth/login.dart';
import 'package:applielikya/views/homepage.dart';
import 'package:applielikya/widgets/createRoute.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
@override
State<LoginPage> createState() => LoginPageState();
}
enum ButtonState { init, loading, done }
class LoginPageState extends State<LoginPage> {
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
final FlutterSecureStorage storage = const FlutterSecureStorage();
ButtonState _state = ButtonState.init;
bool _passwordVisible = false;
final TextEditingController _usernameController = TextEditingController(text: "kentay");
final TextEditingController _passwordController = TextEditingController(text: "kentay");
bool _isAuth = false;
String _responseMessage = "";
void saveToken(SuccessResponse response) async {
await storage.write(key: "accessToken", value: response.accessToken);
await storage.write(key: "refreshToken", value: response.refreshToken);
}
void saveUser(UserResponse user) async {
final SharedPreferences prefs = await _prefs;
prefs.setString('username', user.username as String);
prefs.setInt('id', user.id as int);
prefs.setString('role', user.role as String);
if (user.role == "prof") {
prefs.setString("firstname", user.firstname!);
prefs.setString("lastname", user.lastname!);
prefs.setString("email", user.email!);
}
}
submitLogin() async {
setState(() => _state = ButtonState.loading);
final response = await login(
UserRequest(username : _usernameController.text, password: _passwordController.text)
);
setState(() {
_isAuth = response.auth;
_state = ButtonState.done;
});
if (response is SuccessResponse) {
saveToken(response);
saveUser(response.user);
setState(() => _state = ButtonState.init);
Navigator.of(context).push(
createRoute(
const MyHomePage(),
const Offset(0.0, 1.0),
Offset.zero,
Curves.easeInCirc
)
);
} else {
if (response is ErrorResponse) {
setState(() => _responseMessage = response.message);
}
}
}
如果它对某人有帮助,我通过在设备参数中清除模拟器上应用程序的数据和缓存来修复它。
我正在使用 flutter 安全存储 (^5.0.2) 来保存令牌,但是在模拟器上调用 storage.write() 时出现以下错误(我正在使用 Pixel 5 API 30) 而当我在我的物理设备 (Honor 8x) 上使用它时它运行良好:
PlatformException (PlatformException(Exception encountered, write, java.lang.NullPointerException: Attempt to invoke interface method 'byte[] com.it_nomads.fluttersecurestorage.ciphers.StorageCipher.encrypt(byte[])' on a null object reference
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.write(FlutterSecureStoragePlugin.java:202)
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access0(FlutterSecureStoragePlugin.java:37)
at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:289)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)
, null))
这是调试的输出:
W/KeyStore( 2975): KeyStore exception
W/KeyStore( 2975): android.os.ServiceSpecificException: (code 7)
W/KeyStore( 2975): at android.os.Parcel.createExceptionOrNull(Parcel.java:2387)
W/KeyStore( 2975): at android.os.Parcel.createException(Parcel.java:2357)
W/KeyStore( 2975): at android.os.Parcel.readException(Parcel.java:2340)
W/KeyStore( 2975): at android.os.Parcel.readException(Parcel.java:2282)
W/KeyStore( 2975): at android.security.keystore.IKeystoreService$Stub$Proxy.get(IKeystoreService.java:988)
W/KeyStore( 2975): at android.security.KeyStore.get(KeyStore.java:233)
W/KeyStore( 2975): at android.security.KeyStore.get(KeyStore.java:222)
W/KeyStore( 2975): at android.security.keystore.AndroidKeyStoreSpi.engineGetCertificate(AndroidKeyStoreSpi.java:165)
W/KeyStore( 2975): at java.security.KeyStore.getCertificate(KeyStore.java:1120)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.getPublicKey(RSACipher18Implementation.java:90)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.wrap(RSACipher18Implementation.java:39)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:52)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.ensureInitialized(FlutterSecureStoragePlugin.java:95)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access0(FlutterSecureStoragePlugin.java:37)
W/KeyStore( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:284)
W/KeyStore( 2975): at android.os.Handler.handleCallback(Handler.java:938)
W/KeyStore( 2975): at android.os.Handler.dispatchMessage(Handler.java:99)
W/KeyStore( 2975): at android.os.Looper.loop(Looper.java:223)
W/KeyStore( 2975): at android.os.HandlerThread.run(HandlerThread.java:67)
E/FlutterSecureStoragePl( 2975): StorageCipher initialization failed
E/FlutterSecureStoragePl( 2975): java.lang.Exception: No certificate found under alias: com.example.applielikya.FlutterSecureStoragePluginKey
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.getPublicKey(RSACipher18Implementation.java:92)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.RSACipher18Implementation.wrap(RSACipher18Implementation.java:39)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.ciphers.StorageCipher18Implementation.<init>(StorageCipher18Implementation.java:52)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.ensureInitialized(FlutterSecureStoragePlugin.java:95)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin.access0(FlutterSecureStoragePlugin.java:37)
E/FlutterSecureStoragePl( 2975): at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run(FlutterSecureStoragePlugin.java:284)
E/FlutterSecureStoragePl( 2975): at android.os.Handler.handleCallback(Handler.java:938)
E/FlutterSecureStoragePl( 2975): at android.os.Handler.dispatchMessage(Handler.java:99)
E/FlutterSecureStoragePl( 2975): at android.os.Looper.loop(Looper.java:223)
E/FlutterSecureStoragePl( 2975): at android.os.HandlerThread.run(HandlerThread.java:67)
我不知道它是否相关,但我的代码中有 min Sdk 19,因为一些包需要这个版本。
我需要这个来启动我的物理设备和 Vscode 上的模拟器,在我的应用程序中使用两个不同的帐户(一个管理员和一个用户)来检查通知从一个到另一个的传输,如果另一个实现这一目标的方法存在,我也会知道。
这是代码:
import 'package:applielikya/models/login_response.dart';
import 'package:applielikya/models/user.dart';
import 'package:applielikya/services/auth/login.dart';
import 'package:applielikya/views/homepage.dart';
import 'package:applielikya/widgets/createRoute.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
@override
State<LoginPage> createState() => LoginPageState();
}
enum ButtonState { init, loading, done }
class LoginPageState extends State<LoginPage> {
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
final FlutterSecureStorage storage = const FlutterSecureStorage();
ButtonState _state = ButtonState.init;
bool _passwordVisible = false;
final TextEditingController _usernameController = TextEditingController(text: "kentay");
final TextEditingController _passwordController = TextEditingController(text: "kentay");
bool _isAuth = false;
String _responseMessage = "";
void saveToken(SuccessResponse response) async {
await storage.write(key: "accessToken", value: response.accessToken);
await storage.write(key: "refreshToken", value: response.refreshToken);
}
void saveUser(UserResponse user) async {
final SharedPreferences prefs = await _prefs;
prefs.setString('username', user.username as String);
prefs.setInt('id', user.id as int);
prefs.setString('role', user.role as String);
if (user.role == "prof") {
prefs.setString("firstname", user.firstname!);
prefs.setString("lastname", user.lastname!);
prefs.setString("email", user.email!);
}
}
submitLogin() async {
setState(() => _state = ButtonState.loading);
final response = await login(
UserRequest(username : _usernameController.text, password: _passwordController.text)
);
setState(() {
_isAuth = response.auth;
_state = ButtonState.done;
});
if (response is SuccessResponse) {
saveToken(response);
saveUser(response.user);
setState(() => _state = ButtonState.init);
Navigator.of(context).push(
createRoute(
const MyHomePage(),
const Offset(0.0, 1.0),
Offset.zero,
Curves.easeInCirc
)
);
} else {
if (response is ErrorResponse) {
setState(() => _responseMessage = response.message);
}
}
}
如果它对某人有帮助,我通过在设备参数中清除模拟器上应用程序的数据和缓存来修复它。