gpt4 book ai didi

Android 登录 - 帐户验证器与手动验证

转载 作者:IT老高 更新时间:2023-10-28 21:38:58 26 4
gpt4 key购买 nike

我即将在我的应用程序中实现登录和用户身份验证。

我的第一个想法是手动完成,向服务器注册用户名和密码,获取身份验证 token ,保存并在后续请求中使用它。

在谷歌搜索之后,我发现在 Android 上执行此操作的正确方法是使用 Account Authenticator。我已经看到了一些它的实现示例,但我不明白这样做的好处是什么?是因为我可以存储多个帐户吗?是因为同步问题吗?如果有人可以向我解释这一点,我将不胜感激。它可能会让我更好地理解它的代码以及它为什么这样做。

最佳答案

I can have more than one account stored?



是的。看看如何 谷歌 Facebook 做。

Is it because of syncing issues?



是的,您需要帐户才能使用同步机制,如 SyncAdapter
为什么你应该使用 AccountAuthenticator ?
  • 支持SyncAdapter等后台同步机制;
  • 认证用户的标准方式;
  • 支持不同的代币;
  • 不同权限的账号共享

  • 你需要做什么?

    1)。创建 Authenticator ;

    2)。创建 Activity用于用户登录;

    3)。创建 Service与帐户进行通信。

    条款。

    AccountManager - 它管理设备上的帐户。请求您应该使用的身份验证 token AccountManager .

    AbstractAccountAuthenticator - 用于处理帐户类型的组件。它包含使用帐户的所有逻辑(授权、访问权限等)一个 AbstractAccountAuthenticator可能由不同的应用程序使用(如 Gmail、日历、驱动器等的 Google 帐户)

    AccountAuthenticatorActivity - 基础 Activity , 用于授权/创建帐户。 AccountManager如果需要识别帐户,则调用此帐户( token 不存在或已过期)

    这一切是如何运作的?看下面的图片:

    android account management diagram

    脚步。

    1)。创建 Authenticator ;

    您需要延长 AbstractAccountAuthenticator并覆盖 7 个方法:
  • Bundle editProperties(AccountAuthenticatorResponse response, String
    accountType)
    link
  • Bundle addAccount(AccountAuthenticatorResponse response, String
    accountType, String authTokenType, String[] requiredFeatures, Bundle
    options)
    link
  • Bundle confirmCredentials(AccountAuthenticatorResponse response,
    Account account, Bundle options)
    link
  • Bundle getAuthToken(AccountAuthenticatorResponse response, Account
    account, String authTokenType, Bundle options)
    link
  • String getAuthTokenLabel(String authTokenType) link
  • Bundle updateCredentials(AccountAuthenticatorResponse response,
    Account account, String authTokenType, Bundle options)
    link
  • Bundle hasFeatures(AccountAuthenticatorResponse response, Account
    account, String[] features)
    link

  • 例子:
    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;
    }
    }

    解释:

    因此,您只需要查看 2 个方法: 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" />

    方法总结 addAccountgetAuthToken
    尝试获取token,如果token存在则返回结果,否则会看到 Activity授权

    2)。创建 Activity用于用户登录;

    AuthenticatorActivity

    简要说明:
    使用 UserId 和 Password 创建表单。使用 UserId & Password 数据从服务器获取身份验证 token ,然后执行以下步骤:
    mAccountManager.addAccountExplicitly(account, accountPassword, null);
    mAccountManager.setAuthToken(account, authtokenType, authtoken);

    3)。创建 Service与帐户进行通信。

    UdinicAuthenticatorService

    不要忘记在 AndroidManifest.xml 中添加这一行至 Service :
        <intent-filter>
    <action android:name="android.accounts.AccountAuthenticator" />
    </intent-filter>
    <meta-data android:name="android.accounts.AccountAuthenticator"
    android:resource="@xml/authenticator" />

    还有 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"/>

    就这样。您可以使用您的 AccountAuthenticator .

    源 Material 感谢
  • Udi Cohen ;
  • Daniel Serdyukov (所有文字都翻译自他的文章(除了我的
    小补充) “android 应用程序中的同步。第 1 部分”
    仅限俄语。关联:
    http://habrahabr.ru/company/e-Legion/blog/206210/ )
  • 关于Android 登录 - 帐户验证器与手动验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31915642/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com