【问题标题】:iOS - AWS Cognito - Check if user already existsiOS - AWS Cognito - 检查用户是否已经存在
【发布时间】:2017-04-08 03:13:17
【问题描述】:

我想允许用户在字段中输入他们的电子邮件地址/密码。继续后,我想检查该用户是否已经存在。如果有,请登录并继续使用应用程序,如果没有,请转到帐户创建流程,指示他们添加姓名、电话号码等。

我终生找不到有关如何使用 AWS Cognito 登录用户的文档。我应该能够通过电子邮件/通过电话并得到回复说用户存在/用户不存在或其他什么!我在这里遗漏了什么吗?

任何帮助将不胜感激。我已经浏览了文档。这是我最后的手段。

【问题讨论】:

  • 我以为我不久前看到了亚马逊作为身份验证提供商的标题。我环顾四周找不到那篇文章。当我尝试使用亚马逊的移动中心创建一个应用程序时,它没有亚马逊提供商只有第 3 方的选项。我认为您无法通过亚马逊对其进行身份验证。唯一的方法要么使用 Facebook 等,要么建立自己的身份提供者。正如您可能已经看到的 AWS 文章,在这篇文章中显示 docs.aws.amazon.com/cognito/latest/developerguide/…
  • @yan 。现在我们可以在AWS mobile hub 中添加Amazon cognito user pool 作为身份提供者。阅读这篇文章aws.amazon.com/blogs/mobile/…。我认为最受欢迎的功能:)。
  • @Karthick 我以为亚马逊已经在做这个了。我可能看过一篇关于它处于测试阶段的帖子。感谢您的链接和澄清!
  • @Yan,好的编码愉快:)

标签: ios swift amazon-web-services amazon-cognito


【解决方案1】:

在当前的 SDK 中,在 AWSCognitoIdentityUserPool 上调用 getUser 只会构造内存中的用户对象。要通过网络进行调用,您需要在构造的用户上调用getSession 方法。这是我编写的用于检查电子邮件是否可用的 Swift 3 方法:

/// Check whether an email address is available.
///
/// - Parameters:
///   - email: Check whether this email is available.
///   - completion: Called on completion with parameter true if email is available, and false otherwise.
func checkEmail(_ email: String, completion: @escaping (Bool) -> Void) {
        let proposedUser = CognitoIdentityUserPoolManager.shared.pool.getUser(email)
        UIApplication.shared.isNetworkActivityIndicatorVisible = true
        proposedUser.getSession(email, password: "deadbeef", validationData: nil).continueWith(executor: AWSExecutor.mainThread(), block: { (awsTask) in
            UIApplication.shared.isNetworkActivityIndicatorVisible = false
            if let error = awsTask.error as? NSError {
                // Error implies login failed. Check reason for failure
                let exceptionString = error.userInfo["__type"] as! String
                if let exception = AWSConstants.ExceptionString(rawValue: exceptionString) {
                    switch exception {
                    case .notAuthorizedException, .resourceConflictException:
                        // Account with this email does exist.
                        completion(false)
                    default:
                        // Some other exception (e.g., UserNotFoundException). Allow user to proceed.
                        completion(true)
                    }
                } else {
                    // Some error we did not recognize. Optimistically allow user to proceed.
                    completion(true)
                }
            } else {
                // No error implies login worked (edge case where proposed email
                // is linked with an account which has password 'deadbeef').
                completion(false)
            }
            return nil
        })
    }

作为参考,我的ExceptionString 枚举如下所示:

public enum ExceptionString: String {
    /// Thrown during sign-up when email is already taken.
    case aliasExistsException = "AliasExistsException"
    /// Thrown when a user is not authorized to access the requested resource.
    case notAuthorizedException = "NotAuthorizedException"
    /// Thrown when the requested resource (for example, a dataset or record) does not exist.
    case resourceNotFoundException = "ResourceNotFoundException"
    /// Thrown when a user tries to use a login which is already linked to another account.
    case resourceConflictException = "ResourceConflictException"
    /// Thrown for missing or bad input parameter(s).
    case invalidParameterException = "InvalidParameterException"
    /// Thrown during sign-up when username is taken.
    case usernameExistsException = "UsernameExistsException"
    /// Thrown when user has not confirmed his email address.
    case userNotConfirmedException = "UserNotConfirmedException"
    /// Thrown when specified user does not exist.
    case userNotFoundException = "UserNotFoundException"
}

【讨论】:

  • 没有密码的情况下怎么办。例如,用户输入用户名,应用程序必须确定其是新用户还是现有用户,并分别显示创建或输入密码提示
  • 您可以使用任意占位符作为密码。请注意getSession(email, password: "deadbeef", ...) 中硬编码的“deadbeef”密码。
【解决方案2】:

需要澄清一下。 Cognito 有几个部分。执行“身份验证”(您正在谈论的内容)的部分称为“Cognito 用户池”。不要与 Cognito 联合身份池混淆。

使用用户池,您可以创建具有属性的用户名和密码组合,这些可用于对用户进行身份验证并向用户提供持久的、跨设备的 Cognito 联合身份 identityId(跨多个设备)。

登录后,联合身份池将与角色挂钩,这些角色可以让您“授权”使用 AWS 服务(如 Dynamo DB 等)。

让所有这些部分一起工作可能很棘手,AWS 有一个名为“Mobile Hub”的在线站点,它将为您构建代码并下载一个 xcode 项目。此过程正确配置联合身份池和用户池,并将它们全部连接到一组示例代码。

将凭证提供程序连接到用户池和身份池有点违反直觉,但 github 上的 aws-mobilehub-helper-ios 中的 AWSIdentityManager 会为您管理所有这些。所以我建议从控制台上的移动集线器开始。

Cognito 是一个有点令人困惑的系统,这里有一个指向 brief powerpoint 的链接,其中重点介绍了它的工作原理(适用于无法理解 AWS 文档的人(比如我)。

话虽如此,“如何检查用户是否已经存在?”

最合理的方法是创建用户(通过注册),如果名称正在使用则拒绝,并建议您的用户尝试不同的用户名。关于正在使用的电子邮件,您将在确认后收到拒绝(注册通过电子邮件和/或文本发送确认 ID)。这可以被覆盖以回收电子邮件地址,或者您可以通过尝试登录并查看失败代码来预先进行测试以查看电子邮件是否正在使用中。

您可以按照其他答案的建议获取用户,但是如果您在用户池中建立了登录别名(如电子邮件),您会发现这有问题,因为这只是告诉您是否有人拥有用户名,而不是如果有人已经在使用该电子邮件地址,您将在稍后确认时收到拒绝。

【讨论】:

    【解决方案3】:

    ListUsers 现在是检查现有用户名的好方法。

    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html

    您还可以查找现有的电子邮件、电话号码和其他默认属性。

    这是一个简单的 .NET 示例:

        Dim userRequest = New ListUsersRequest With {
                .UserPoolId = "poolId",
                .Filter = "username = bob@email.com"
            }
        Dim response = amazonCognitoIdentityProviderClient.ListUsers(userRequest)
        Debug.WriteLine(response.Users.Count)
    

    【讨论】:

      猜你喜欢
      • 2021-08-28
      • 2021-02-04
      • 2015-05-05
      • 1970-01-01
      • 2018-08-06
      • 2019-08-04
      • 1970-01-01
      • 1970-01-01
      • 2023-01-28
      相关资源
      最近更新 更多