其他应用程序可以访问客户经理中的用户数据

时间:2015-03-19 07:17:14

标签: android security sharedpreferences account accountmanager

我正在尝试使用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中存储它们的区别是什么?

2 个答案:

答案 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