这是我的问题:
我有一个程序需要密码才能工作,所以我想我可以创建一个AccountManager。我从this tutorial获取了代码并且工作正常:我在设置>帐户中有一个新帐户!
但是来测试它是否安全我使用相同的代码执行了另一个程序(让我们称之为 Prog2 和第一个 Prog1 )并且,我可以完全访问使用Prog1使用Prog2创建的帐户的密码。
我知道可以保护帐户,因为我尝试使用谷歌和Facebook帐户,但我无法访问他们的密码。
这是我的代码:
PS :如果在字符串的末尾有一个' 1'它是因为我在Prog1中而不是在Prog2中更改它来测试这些变量是否有一些影响
身份验证
public class Authenticator extends AbstractAccountAuthenticator {
private String TAG = "CoderzHeavenAuthenticator";
private final Context mContext;
public Authenticator(Context context) {
super(context);
// I hate you! Google - set mContext as protected!
this.mContext = context;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
Log.d("CoderzHeaven", TAG + "> addAccount");
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.ARG_ACCOUNT_TYPE, accountType);
intent.putExtra(AuthenticatorActivity.ARG_AUTH_TYPE, authTokenType);
intent.putExtra(AuthenticatorActivity.ARG_IS_ADDING_NEW_ACCOUNT, true);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
Log.d("CoderzHeaven", TAG + "> getAuthToken");
// If the caller requested an authToken type we don't support, then
// return an error
if (!authTokenType.equals(AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY) && !authTokenType.equals(AUTHTOKEN_TYPE_FULL_ACCESS)) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
return result;
}
// Extract the username and password from the Account Manager, and ask
// the server for an appropriate AuthToken.
final AccountManager am = AccountManager.get(mContext);
String authToken = am.peekAuthToken(account, authTokenType);
Log.d("CoderzHeaven", TAG + "> peekAuthToken returned - " + authToken);
// Lets give another try to authenticate the user
if (TextUtils.isEmpty(authToken)) {
final String password = am.getPassword(account);
if (password != null) {
try {
Log.d("CoderzHeaven", TAG + "> re-authenticating with the existing password");
//authToken = sServerAuthenticate.userSignIn(account.name, password, authTokenType);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// If we get an authToken - we return it
if (!TextUtils.isEmpty(authToken)) {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
return result;
}
// If we get here, then we couldn't access the user's password - so we
// need to re-prompt them for their credentials. We do that by creating
// an intent to display our AuthenticatorActivity.
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
intent.putExtra(AuthenticatorActivity.ARG_ACCOUNT_TYPE, account.type);
intent.putExtra(AuthenticatorActivity.ARG_AUTH_TYPE, authTokenType);
intent.putExtra(AuthenticatorActivity.ARG_ACCOUNT_NAME, account.name);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public String getAuthTokenLabel(String authTokenType) {
if (AUTHTOKEN_TYPE_FULL_ACCESS.equals(authTokenType))
return AUTHTOKEN_TYPE_FULL_ACCESS_LABEL;
else if (AUTHTOKEN_TYPE_READ_ONLY.equals(authTokenType))
return AUTHTOKEN_TYPE_READ_ONLY_LABEL;
else
return authTokenType + " (Label)";
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
final Bundle result = new Bundle();
result.putBoolean(KEY_BOOLEAN_RESULT, false);
return result;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
return null;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
}
AuthenticatorService
public class AuthenticatorService extends Service {
private Authenticator authenticator;
public AuthenticatorService() {
super();
}
public IBinder onBind(Intent intent) {
IBinder ret = null;
if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT))
ret = getAuthenticator().getIBinder();
return ret;
}
private Authenticator getAuthenticator() {
if (authenticator == null)
authenticator = new Authenticator(this);
return authenticator;
}
}
AuthenticatorActivity
public class AuthenticatorActivity extends AccountAuthenticatorActivity implements OnClickListener{
public final static String ARG_ACCOUNT_TYPE = "ACCOUNT_TYPE1";
public final static String ARG_AUTH_TYPE = "AUTH_TYPE1";
public final static String ARG_ACCOUNT_NAME = "ACCOUNT_NAME1";
public final static String ARG_IS_ADDING_NEW_ACCOUNT = "IS_ADDING_ACCOUNT1";
public static final String KEY_ERROR_MESSAGE = "ERR_MSG1";
public final static String PARAM_USER_PASS = "USER_PASS1";
private final String TAG = this.getClass().getSimpleName();
private AccountManager mAccountManager;
private String mAuthTokenType;
String authtoken = "12345678910"; // this
String password = "1234510";
String accountName;
public Account findAccount(String accountName) {
for (Account account : mAccountManager.getAccounts())
if (TextUtils.equals(account.name, accountName) && TextUtils.equals(account.type, getString(R.string.auth_type))) {
System.out.println("FOUND");
return account;
}
return null;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_login);
Log.d(TAG, "onCreate");
mAccountManager = AccountManager.get(getBaseContext());
// If this is a first time adding, then this will be null
accountName = getIntent().getStringExtra(ARG_ACCOUNT_NAME);
mAuthTokenType = getIntent().getStringExtra(ARG_AUTH_TYPE);
if (mAuthTokenType == null)
mAuthTokenType = getString(R.string.auth_type);
findAccount(accountName);
System.out.println(mAuthTokenType + ", accountName : " + accountName);
((Button)findViewById(R.id.submit)).setOnClickListener(this);
}
void userSignIn() {
// You should probably call your server with user credentials and get
// the authentication token here.
// For demo, I have hard-coded it.
authtoken = "12345678910";
accountName = ((EditText) findViewById(R.id.accountName)).getText().toString().trim();
password = ((EditText) findViewById(R.id.accountPassword)).getText().toString().trim();
if (accountName.length() > 0) {
Bundle data = new Bundle();
data.putString(AccountManager.KEY_ACCOUNT_NAME, accountName);
data.putString(AccountManager.KEY_ACCOUNT_TYPE, mAuthTokenType);
data.putString(AccountManager.KEY_AUTHTOKEN, authtoken);
data.putString(PARAM_USER_PASS, password);
// Some extra data about the user
Bundle userData = new Bundle();
userData.putString("UserID", "25");
data.putBundle(AccountManager.KEY_USERDATA, userData);
//Make it an intent to be passed back to the Android Authenticator
final Intent res = new Intent();
res.putExtras(data);
//Create the new account with Account Name and TYPE
final Account account = new Account(accountName, mAuthTokenType);
//Add the account to the Android System
if (mAccountManager.addAccountExplicitly(account, password, userData)) {
// worked
Log.d(TAG, "Account added");
mAccountManager.setAuthToken(account, mAuthTokenType, authtoken);
setAccountAuthenticatorResult(data);
setResult(RESULT_OK, res);
finish();
} else {
// guess not
Log.d(TAG, "Account NOT added");
}
}
}
@Override
public void onClick(View v) {
userSignIn();
}
}
AccountGeneral
public class AccountGeneral {
/**
* Account name
*/
public static final String ACCOUNT_NAME = "CoderzHeaven1";
/**
* Auth token types
*/
public static final String AUTHTOKEN_TYPE_READ_ONLY = "Read only1";
public static final String AUTHTOKEN_TYPE_READ_ONLY_LABEL = "Read only access to an CoderzHeaven account1";
public static final String AUTHTOKEN_TYPE_FULL_ACCESS = "Full access1";
public static final String AUTHTOKEN_TYPE_FULL_ACCESS_LABEL = "Full access to an CoderzHeaven account1";
}
答案 0 :(得分:0)
正如Google文档所述,AccountManager不是加密服务。 See here
与root设备相比,这是一个很好的选择。或者“您应该存储对攻击者使用有限的加密安全令牌”(来自Google文档)
编辑:
如果您有访问Program2的权限,那是因为您使用(或根本不使用)相同的密钥库来签署您的apk。具有相同签名的应用程序可以访问accountManager字段