我正在创建一个 android 应用程序,但我无法(?)找到任何有关在 Google App Engine 上验证应用程序用户的信息(不使用用户的 Google 帐户)。将用户名和密码存储在 android 设备上是一种好习惯吗?然后将应用程序使用的数据存储在 Google App Engine 上?
3 回答
尽管谷歌会告诉你它们有多安全,但你不应该使用SharedPreferences
,因为根植习惯在权力和想要成为权力的用户中都很普遍。
在根系统中,授权的应用程序将能够访问内部存储/系统分区,从而访问根拥有的加密 XML 文件,其中 Android 存储 SharedPreferences,这成为根授权应用程序的明文。因此,如果受感染的手机碰巧有一个存储此类数据的应用程序,并且用户有滥用不同服务的相同电子邮件/密码的习惯,那么攻击向量很容易破坏多个服务的凭据,尽管用户在使用时忽略了任何警告生根他的手机或授予应用程序这样的权限,因为,好吧,这些警告还不够清楚。
替代方法是手动加密凭据的持久存储,使用自定义、可变种子、加盐算法。secure-preferences lib 是一个很好的替代方案,它几乎以透明的方式为您完成所有工作,并具有实现 Android 的 SharedPreferences 接口的额外好处,保留了默认 sprefs 的大多数功能,只需稍作调整(查看他们的示例)。
2016 年编辑:我只是觉得我需要在 2016 年回到这个问题,并添加一个很好的参考Apple vs FBI 戏剧来改变圣贝纳迪诺袭击者手机中的操作系统。所以,想象一下你有一部很容易root的手机,就像大多数Android手机一样,它甚至可能默认root或者不需要将数据擦除到root。如果 FBI 不想获取您的凭据,他们无需向 Google 或您的公司提出任何要求。通过使用诸如安全首选项之类的东西,您将承担与 Apple 决定承担的相同类型的责任,即仅使您自己的系统(在本例中为您的应用程序)能够访问这些凭据。如果 FBI 愿意,您确实会感到恼火,但是让您的用户感觉到您,而不是底层操作系统,是唯一可以直接控制这些凭据的权威,这是我宁愿在我的产品中拥有的东西。
您可以将用户凭据保存在共享首选项中。您可以在任何活动中使用此偏好值。即使退出应用程序,保存的值也会保留。共享首选项的示例代码在这里。建议将您的首选项代码保留在您的应用程序 utils 类中,以使您的代码井井有条。
public static String KEY = "SESSION";
public static void saveUserName(String userid, Context context) {
Editor editor = context
.getSharedPreferences(KEY, Activity.MODE_PRIVATE).edit();
editor.putString("username", userid);
editor.commit();
}
public static String getUserName(Context context) {
SharedPreferences savedSession = context.getSharedPreferences(KEY,
Activity.MODE_PRIVATE);
return savedSession.getString("username", "");
}
为此考虑SharedPreferences,例如...
public class PrefUtils {
public static final String PREFS_LOGIN_USERNAME_KEY = "__USERNAME__" ;
public static final String PREFS_LOGIN_PASSWORD_KEY = "__PASSWORD__" ;
/**
* Called to save supplied value in shared preferences against given key.
* @param context Context of caller activity
* @param key Key of value to save against
* @param value Value to save
*/
public static void saveToPrefs(Context context, String key, String value) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences.Editor editor = prefs.edit();
editor.putString(key,value);
editor.commit();
}
/**
* Called to retrieve required value from shared preferences, identified by given key.
* Default value will be returned of no value found or error occurred.
* @param context Context of caller activity
* @param key Key to find value against
* @param defaultValue Value to return if no data found against given key
* @return Return the value found against given key, default if not found or any error occurs
*/
public static String getFromPrefs(Context context, String key, String defaultValue) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
try {
return sharedPrefs.getString(key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
return defaultValue;
}
}
}
只需使用这些方法,例如,
// Saving user credentials on successful login case
PrefUtils.saveToPrefs(YourActivity.this, PREFS_LOGIN_USERNAME_KEY, username);
PrefUtils.saveToPrefs(YourActivity.this, PREFS_LOGIN_PASSWORD_KEY, password);
// To retrieve values back
String loggedInUserName = PrefUtils.getFromPrefs(YourActivity.this, PREFS_LOGIN_USERNAME_KEY);
String loggedInUserPassword = PrefUtils.getFromPrefs(YourActivity.this, PREFS_LOGIN_PASSWORD_KEY);
我认为它现在更清楚了...... :)