我正在尝试使用Android的帐户管理器来存储用户的应用凭据。 虽然我没有保存用户的密码,但我想将其他安全密钥保存到帐户的UserData中。根据下面引用的文档,具有不同UID的应用程序不应该访问它。
public String getUserData(帐户帐户,字符串键)
获取与该帐户关联的“key”命名的用户数据。这适用于验证者和相关代码,用于存储任意元数据和帐户。密钥和值的含义取决于帐户的验证者。
从主线程调用此方法是安全的。
此方法要求调用者持有权限AUTHENTICATE_ACCOUNTS并拥有与帐户验证者相同的UID。
参数 account - 要查询用户数据的帐户 返回 用户数据,如果帐户或密钥不存在,则为null
为了测试这一点,我创建了一个创建帐户并将一些内容保存到UserData的应用程序。我还创建了另一个访问第一个应用程序帐户的应用程序。以下是片段:
第一个应用:
AccountManager am = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
final Account account = new Account("Account Name", "my.account.type");
am.addAccountExplicitly(account, null, null);
am.setAuthToken(account, "my.account.type", "some auth token");
am.setUserData(account, "key.for.secure.user.data", "some secure data");
第二个应用:
AccountManager am = (AccountManager)context.getSystemService(Context.ACCOUNT_SERVICE);
Account[] accountsFromFirstApp = am.getAccountsByType("my.account.type");
for(Account acct: accountsFromFirstApp){
printToLogs(acct.name);
printToLogs(am.getUserData(acct, "key.for.secure.user.data"));
}
根据上面的文档,我希望第二个应用程序的getUserData()返回一个异常,因为它没有与所有者应用程序相同的UID。令人惊讶的是,我能够毫无错误地访问第一个应用程序的用户数据。
但是当我尝试使用“com.google”作为帐户类型从谷歌访问帐户时,我得到了预期的例外。
我的实施有什么问题?我是否错过了Android文档中未说明的配置?任何帮助将非常感谢。
第二个想法,如果可以轻松访问这些用户数据(假设其他应用程序知道我的应用程序的帐户类型),那么将UserData中的字符串存储在SharedPreferences中存储它们的区别是什么?
答案 0 :(得分:0)
来自AccountManager文档:
此类提供对用户在线帐户的集中注册表的访问。用户每个帐户输入一次凭据(用户名和密码),通过“一键”批准授予应用程序访问在线资源的权限。
AccountManager管理的帐户是集中的,可重复使用的,例如所有Google应用都可以使用同一个帐户,并非每个应用都必须创建自己的Google帐户。
因此,据我所知,AccountManager的一个想法是拥有可重复使用的帐户,可以从不同的应用程序访问。
但由于可以从不同的地方访问存储的凭据,因此不应在AccountManager中存储任何纯文本密码。
愿这个主题对你有用:What should I use AccountManager for?
答案 1 :(得分:0)
如果您的数据是个人数据,则可以对其进行加密,因此其他应用程序都无法读取它们。
使用AES加密的I.E:
public class AESCryptor
{
private static final String ALGORITHM = "AES";
// 16-bit Key for encryption (Change to yours)
private static final String KEY = "XXXXXXXXXXXXXXX";
public static String encrypt(String value) throws Exception
{
Key key = generateKey();
@SuppressLint("GetInstance") Cipher cipher = Cipher.getInstance(AESCryptor.ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte [] encryptedByteValue = cipher.doFinal(value.getBytes("utf-8"));
return Base64.encodeToString(encryptedByteValue, Base64.DEFAULT);
}
public static String decrypt(String value) throws Exception
{
Key key = generateKey();
@SuppressLint("GetInstance") Cipher cipher = Cipher.getInstance(AESCryptor.ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedValue64 = Base64.decode(value, Base64.DEFAULT);
byte [] decryptedByteValue = cipher.doFinal(decryptedValue64);
return new String(decryptedByteValue,"utf-8");
}
private static Key generateKey() {
return new SecretKeySpec(AESCryptor.KEY.getBytes(),AESCryptor.ALGORITHM);
}
}
我在我的应用程序中使用它,并且可以正常工作!
这可能无法回答问题
其他应用程序可以访问帐户管理器中的用户数据
但是它由@ thomas-s-e回答
关于, @developerfromjokela