Dan*_*lio 37 authentication android login accountmanager
我即将在我的应用程序中实现登录以及用户身份验证.
我的第一个想法是手动完成,向服务器注册用户名和密码,获取身份验证令牌,保存并在后续请求中使用它.
谷歌搜索后,我认为在Android上正确的方法是使用帐户身份验证器.我已经看到了一些它的实现的例子,但是我不明白这样做的好处呢?是因为我可以存储多个帐户吗?是因为同步问题吗?如果有人能向我解释,我会很感激.它可能会让我更好地理解它的代码以及它为什么会这样做.
Ale*_*der 103
我可以存储多个帐户吗?
是.了解Google或Facebook如何 做到这一点.
是因为同步问题吗?
是的,您需要帐户才能使用同步机制 SyncAdapter
你为什么要用AccountAuthenticator?
支持后台同步机制如SyncAdapter;
验证用户的标准方法;
支持不同的令牌;
帐户共享具有不同的权限
你需要做什么?
1).创造Authenticator;
2).创建Activity用户登录;
3).创建Service与帐户进行通信.
AccountManager - 它管理设备上的帐户.请求您应该使用的auth令牌AccountManager.
AbstractAccountAuthenticator - 用于处理帐户类型的组件.它包含用于处理帐户的所有逻辑(授权,访问权限等).AbstractAccountAuthenticator可以由不同的应用程序使用(例如Gmail帐户,日历,云端硬盘等)
AccountAuthenticatorActivity - base Activity,用于授权/创建帐户.AccountManager如果需要识别帐户(令牌不存在或已过期),则调用此帐户
它是如何工作的?看下面的图片:
1).创造Authenticator;
您需要扩展AbstractAccountAuthenticator和覆盖7种方法:
Bundle editProperties(AccountAuthenticatorResponse response, String
accountType) 链接Bundle addAccount(AccountAuthenticatorResponse response, String
accountType, String authTokenType, String[] requiredFeatures, Bundle
options) 链接Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options) 链接Bundle getAuthToken(AccountAuthenticatorResponse response, Account
account, String authTokenType, Bundle options) 链接String getAuthTokenLabel(String authTokenType) 链接Bundle updateCredentials(AccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle options) 链接Bundle hasFeatures(AccountAuthenticatorResponse response, Account
account, String[] features) 链接例:
public class LodossAuthenticator extends AbstractAccountAuthenticator {
private static final String LOG_TAG = LodossAuthenticator.class.getSimpleName();
private final Context mContext;
public LodossAuthenticator(Context context) {
super(context);
mContext = context;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
return null;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
final Intent intent = new Intent(mContext, CustomServerAuthenticatorSigninActivity.class);
intent.putExtra(Config.ARG_ACCOUNT_TYPE, accountType);
intent.putExtra(Config.ARG_AUTH_TYPE, authTokenType);
intent.putExtra(Config.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 confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
// 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(AccountGeneral.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);
// Lets give another try to authenticate the user
if (TextUtils.isEmpty(authToken)) {
final String password = am.getPassword(account);
if (password != null) {
try {
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(com.lodoss.authlib.Config.ARG_ACCOUNT_TYPE, account.type);
intent.putExtra(com.lodoss.authlib.Config.ARG_AUTH_TYPE, authTokenType);
intent.putExtra(Config.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 (AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS.equals(authTokenType))
return AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS_LABEL;
else if (AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY.equals(authTokenType))
return AccountGeneral.AUTHTOKEN_TYPE_READ_ONLY_LABEL;
else
return authTokenType + " (Label)";
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
说明:
所以,你只需要看到两种方法:addAccount, getAuthToken.
在addAccount我添加了一些配置参数,我将Activity用于用户登录.这里的要点是intent.putExtra(Config.ARG_ACCOUNT_TYPE, accountType);- 您应该在此处指定帐户类型.其他操作不是必需的.
在getAuthToken- 请阅读评论.我从UdinicAuthenticator.java复制粘贴了这个方法
此外,您将需要在AndroidManifest.xml中具有以下权限:
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
Run Code Online (Sandbox Code Playgroud)
addAccount和方法摘要getAuthToken尝试获取令牌,如果令牌存在返回结果,否则您将看到Activity授权
2).创建Activity用户登录;
简要说明: 使用UserId和Password创建表单.使用UserId和Password数据从服务器获取auth令牌,然后执行以下步骤:
mAccountManager.addAccountExplicitly(account, accountPassword, null);
mAccountManager.setAuthToken(account, authtokenType, authtoken);
Run Code Online (Sandbox Code Playgroud)
3).创建一个Service与帐户进行通信.
不要忘记将此行添加AndroidManifest.xml到Service:
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
Run Code Online (Sandbox Code Playgroud)
并且还在res/xml添加文件中authenticator.xml:
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.mediamanagment.app"
android:icon="@drawable/ic_launcher"
android:smallIcon="@drawable/ic_launcher"
android:label="@string/authenticator_label"/>
Run Code Online (Sandbox Code Playgroud)
就这样.你可以使用你的AccountAuthenticator.
乌迪科恩 ;
Daniel Serdyukov(所有文字都是从他的文章翻译过来的(除了我的小补充)"Android应用程序中的同步.第1部分" 仅限俄语.链接:http: //habrahabr.ru/company/e-Legion/blog/206210/)
这AccountManager有好处,原因如下:
Accounts然而,这不是使用的主要原因,因为您可以轻松地在应用程序中管理它,而不需要这种看上去很奇怪的Accounts东西....Accounts是每次用户请求授权功能时都使用用户名和密码来摆脱传统授权,因为身份验证是在后台进行的,并且仅在特定条件下要求用户输入密码,我稍后会谈到它.Accountsandroid中的功能也无需定义自己的帐户类型.您可能会使用Google帐户进行授权,从而节省了创建新帐户和记住用户凭据的麻烦.Accounts 可以通过设置→帐户独立添加Accounts.例如,客户端可以在他们的Android设备和PC中同时访问受保护的材料,而无需重复登录.Accounts在android中使用该功能的一个重要原因是将依赖于Accounts所谓的身份验证者和资源所有者的任何业务中涉及的双方分开,而不会损害客户端(用户)的凭据.这些条款似乎相当含糊,但在阅读以下段落之前不要放弃......让我详细说明后者的视频流应用程序示例.A公司是与B公司签订合同的视频流业务的持有者,为其某些成员提供优质流媒体服务.公司B使用用户名和密码方法来识别其用户.对于公司A来认可B的高级会员,一种方法是从B获取它们的列表并使用类似的用户名/密码匹配机制.这样,验证者和资源所有者是相同的(公司A).除了用户有义务记住第二个密码之外,很可能他们设置的密码与公司B的配置文件相同,以便使用来自A的服务.这显然是不利的.
为了消除上述缺点,引入了OAuth.作为授权的开放标准,在上面的示例中,OAuth要求授权由公司B(身份验证者)通过为符合条件的用户(第三方)发布一些称为访问令牌的令牌,然后向公司A(资源所有者)提供令牌.所以没有令牌意味着没有资格.
我已经阐述了更多关于这和更多的AccountManager在我的网站在这里
| 归档时间: |
|
| 查看次数: |
19139 次 |
| 最近记录: |