如何在 android 中安全地保存 Oauth 访问令牌

How to save Oauth Access token securely in android

身份验证后我从服务器获得了访问令牌 "uyhjjfjfgg567f8fhjkkf" 现在我想将其安全地保存在设备中。我查看了 android 开发者网站中的 Keystore 和 Keychain。我不清楚它是如何工作的以及我们应该如何从密钥库中检索令牌。

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
kpg.initialize(new KeyGenParameterSpec.Builder(
        alias,
        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
        .setDigests(KeyProperties.DIGEST_SHA256,
            KeyProperties.DIGEST_SHA512)
        .build());

KeyPair kp = kpg.generateKeyPair();


/*
 * Load the Android KeyStore instance using the the
 * "AndroidKeyStore" provider to list out what entries are
 * currently stored.
 */

KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
Enumeration<String> aliases = ks.aliases();

您不需要保存访问令牌,因为它的寿命很短。留在记忆中就足够了。

您确实需要保留刷新令牌,为此您有几个选择:

  • 在文件中
    • 要么直接在内部存储的文件中
    • 或使用SharedPreferences
    • 或在数据库中
  • 使用 AccountManager

考虑使用 StoredCredential. For the flow itself, I recommend you to use Google AppAuth library

当然,你也可以使用密码对密钥进行加密:

private static byte[] encrypt(byte[] key, byte[] text) throws GeneralSecurityException {
    final SecretKeySpec skeySpec = new SecretKeySpec(key, KEY_ALGORITHM);
    final Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, sInitVectorSpec);
    return cipher.doFinal(text);
}

并且密钥可以存储在KeyStore

我们使用自定义 SharedPreference 实例,在添加时加密键和值,并在请求时解密。

SecurePreferences preferences = ...
preferences.edit().putString( "key", "value" ).apply(); // key and value are encrypted automatically

String value = preferences.getString( "key", null ); // key and value are decrypted automatically

我只建议在值被加密时使用 SharedPreferences,因为即使 xml 文件仅对应用程序可用,它也可以在获得 root 权限的设备上访问。

如果您已经在使用 SqlLiteDB,我可能会使用它。不然的话,只存一个token就有点重了。

编辑:

oauth 令牌与用于签署应用程序的密钥和密钥库完全无关。

oauth 令牌是服务器在验证用户凭据后在应用程序内提供的令牌。

密钥库包含 1 个或多个用于对应用程序进行数字签名的证书。这是为了防止其他人上传与您的包名相同的应用程序并替换它。