0

我目前正在将 AWS Mobile Hub 用于使用 Cognito 和 Cloud Logic 的 iOS 应用程序。

我决定替换默认的 AuthUIViewController,因为我不喜欢它的外观。我使用这个示例项目来帮助我通过用户池实现注册:https ://github.com/awslabs/aws-sdk-ios-samples/tree/master/CognitoYourUserPools-Sample/Swift 。

这是我的实现:

从我的 AppDelegate 开始,我将要登录的 UserPool 设置为一个通常可访问的常量变量。我对为什么 AWSMobileClient 认为我的用户没有登录的一个想法是因为它定义了自己的服务配置/池,但我不确定:

func application(_ application: UIApplication, didFinishLaunchingWithOptions     launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    AWSDDLog.add(AWSDDTTYLogger.sharedInstance)
    AWSDDLog.sharedInstance.logLevel = .verbose

    // setup service configuration
    let serviceConfiguration = AWSServiceConfiguration(region: Constants.AWS.CognitoIdentityUserPoolRegion, credentialsProvider: nil)

    // create pool configuration
    let poolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: Constants.AWS.CognitoIdentityUserPoolAppClientId,
                                                                    clientSecret: Constants.AWS.CognitoIdentityUserPoolAppClientSecret,
                                                                    poolId: Constants.AWS.CognitoIdentityUserPoolId)

    // initialize user pool client
    AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: poolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)

    // fetch the user pool client we initialized in above step
    Constants.AWS.pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey)

    return AWSMobileClient.sharedInstance().interceptApplication(
        application, didFinishLaunchingWithOptions:
        launchOptions)
} 

AppDelegate 完成后,应用程序转到其名为 InitialViewController 的根视图控制器。在这里,我允许用户单击 facebook 登录或常规(用户池)登录。

class InitialViewController:UIViewController {

@objc func regLogin() {
 //Set a shared constants variable "user" to the current user   
 if (Constants.AWS.user == nil) {
        Constants.AWS.user = Constants.AWS.pool?.currentUser()
    }
    Constants.AWS.pool?.delegate = self

    //This function calls the delegate function startPasswordAuthentication() in the extension below to initiate login
        Constants.AWS.user?.getDetails().continueOnSuccessWith { (task) -> AnyObject? in
            DispatchQueue.main.async(execute: {
    //called after details for user are successfully retrieved after login                
                print(AWSSignInManager.sharedInstance().isLoggedIn)// false
                print(AWSSignInManager.init().isLoggedIn)// false
                print(AWSCognitoUserPoolsSignInProvider.init().isLoggedIn())// false
                print(Constants.AWS.user?.isSignedIn) // true
                AppDelegate.del().signIn()
            })
            return nil
        }
      }
    }

extension InitialViewController: AWSCognitoIdentityInteractiveAuthenticationDelegate {

func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication {
    self.present(loginVC, animated: true, completion: nil)
    return self.loginVC
}
}

如您所见,这些函数完成了它们的工作,并且用户根据 (Constants.AWS.user?.isSignedIn) 成功登录,并且我能够成功检索用户详细信息。但是,当我询问 AWSSignInManager 或 UserPoolsSignInProvider 我的用户是否已登录时,它返回 false。这是一个问题,因为没有 AWSMobileHub 看到我的用户已登录,我无法访问我的云逻辑功能等。

有人可以帮助我了解如何通知 MobileHub 和登录管理器我的用户已登录到用户池,以便我的应用程序可以正常工作吗?

谢谢你!

4

2 回答 2

1

乔纳森的回答是一个很好的起点,但它需要将 AWSAuthUI 包含到您的项目中。

更好的解决方案是直接实现 AWSUserPoolsUIOperations.m 中的函数。特别是,按下登录按钮时触发的功能应如下所示:

@IBAction func signInPressed(_ sender: AnyObject) {
    if (self.usernameTextField.text != nil && self.passwordTextField.text != nil) {

        self.userName = self.usernameTextField.text!
        self.password = self.passwordTextField.text!

        AWSCognitoUserPoolsSignInProvider.sharedInstance().setInteractiveAuthDelegate(self)

        AWSSignInManager.sharedInstance().login(
            signInProviderKey: AWSCognitoUserPoolsSignInProvider.sharedInstance().identityProviderName,
            completionHandler: { (provider: Any?, error: Error?) in
                print(AWSSignInManager.sharedInstance().isLoggedIn)
        })
   } else {
       let alertController = UIAlertController(title: "Missing information",
                                                message: "Please enter a valid user name and password",
                                                preferredStyle: .alert)
       let retryAction = UIAlertAction(title: "Retry", style: .default, handler: nil)
       alertController.addAction(retryAction)
   }
}

然后包含以下函数作为 SignIn 视图控制器的扩展:

public func handleUserPoolSignInFlowStart() {
    let authDetails = AWSCognitoIdentityPasswordAuthenticationDetails(username: self.userName!, password: self.password!)
    self.passwordAuthenticationCompletion?.set(result: authDetails)
}

public func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication {
    return self
}

public func getDetails(_ authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput, passwordAuthenticationCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>) {
    self.passwordAuthenticationCompletion = passwordAuthenticationCompletionSource
}

public func didCompleteStepWithError(_ error: Error?) {
    DispatchQueue.main.async {
        if let error = error as NSError? {
            let alertController = UIAlertController(title: error.userInfo["__type"] as? String,
                                                    message: error.userInfo["message"] as? String,
                                                    preferredStyle: .alert)
            let retryAction = UIAlertAction(title: "Retry", style: .default, handler: nil)
            alertController.addAction(retryAction)

            self.present(alertController, animated: true, completion:  nil)
        } else {
            self.usernameTextField.text = nil
            self.dismiss(animated: true, completion: nil)
        }
    }
}
于 2018-08-13T19:32:21.423 回答
0

在深入研究了 AWS 代码之后,我在 AWSSignInViewController.m 的 pod AWSAuthUI 中找到了答案(移动集线器/cognito 的默认身份验证过程中使用的视图控制器)。

代码是:

- (void)handleUserPoolSignIn {
    Class awsUserPoolsUIOperations = NSClassFromString(USERPOOLS_UI_OPERATIONS);
    AWSUserPoolsUIOperations *userPoolsOperations = [[awsUserPoolsUIOperations alloc] initWithAuthUIConfiguration:self.config];
    [userPoolsOperations loginWithUserName:[self.tableDelegate getValueForCell:self.userNameRow forTableView:self.tableView]
                                  password:[self.tableDelegate getValueForCell:self.passwordRow forTableView:self.tableView]
                      navigationController:self.navigationController
                         completionHandler:self.completionHandler];
}

并仅处理重要的部分……在 Swift 中!

 userPoolsOperations.login(withUserName: "foo", password: "bar", navigationController: self.navigationController!, completionHandler: { (provider: Any?, error: Error?) in
            print(AWSSignInManager.sharedInstance().isLoggedIn) // true
            print(AWSSignInManager.init().isLoggedIn) // false
            print(AWSCognitoUserPoolsSignInProvider.init().isLoggedIn()) // false
            print(Constants.AWS.user?.isSignedIn) // nil
            })
        }

经验教训:阅读 AWS 的代码是有帮助的,尽管它很烂

于 2018-07-13T05:54:25.520 回答