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);
      }
    }
  }

如果它对某人有帮助,我通过在设备参数中清除模拟器上应用程序的数据和缓存来修复它。