Swift AWS Mobile Hub表示用户在自定义UI用户池登录/身份验证后未登录
我目前正在将AWS Mobile Hub用于一个利用Cognito和云逻辑的iOS应用程序 我决定替换默认的AuthUIViewController,因为我不喜欢它的外观。我使用此示例项目帮助我通过用户池实现注册: 以下是我的实现: 从AppDelegate开始,我将要登录的UserPool设置为一个常用的可访问常量变量。我想知道为什么AWSMobileClient认为我的用户没有登录,因为它定义了自己的服务配置/池,但我不确定:Swift AWS Mobile Hub表示用户在自定义UI用户池登录/身份验证后未登录,swift,amazon-web-services,amazon-cognito,aws-mobilehub,aws-userpools,Swift,Amazon Web Services,Amazon Cognito,Aws Mobilehub,Aws Userpools,我目前正在将AWS Mobile Hub用于一个利用Cognito和云逻辑的iOS应用程序 我决定替换默认的AuthUIViewController,因为我不喜欢它的外观。我使用此示例项目帮助我通过用户池实现注册: 以下是我的实现: 从AppDelegate开始,我将要登录的UserPool设置为一个常用的可访问常量变量。我想知道为什么AWSMobileClient认为我的用户没有登录,因为它定义了自己的服务配置/池,但我不确定: func application(_ application:
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和登录经理我的用户已登录到用户池,以便我的应用程序能够正常工作吗
谢谢大家! 在深入研究AWS代码之后,我在AWSSignInViewController.m(移动集线器/cognito的默认身份验证过程中使用的视图控制器)中的pod AWSAuthUI中找到了我的答案 代码是:
- (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];
}
只涉及重要的部分。。。用斯威夫特
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的代码是有帮助的,尽管它很糟糕乔纳森的答案是一个很好的起点,但它需要将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 view控制器的扩展:
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)
}
}
}
public func handleUserPoolSignInFlowStart(){
让authDetails=AWSCognitoIdentityPasswordAuthenticationDetails(用户名:self.username!,密码:self.password!)
self.passwordAuthenticationCompletion?.set(结果:authDetails)
}
public func startPasswordAuthentication()->AWSCognitoIdentityPasswordAuthentication{
回归自我
}
public func getDetails(authenticationInput:AWSCognitoIdentityPasswordAuthenticationInput,passwordAuthenticationCompletionSource:AWSTaskCompletionSource){
self.passwordAuthenticationCompletion=passwordAuthenticationCompletionSource
}
公共函数didCompleteTestepWithError(error:error?){
DispatchQueue.main.async{
如果let error=错误为N错误{
让alertController=UIAlertController(标题:error.userInfo[“\uuu type”]作为?字符串,
消息:错误。userInfo[“消息”]作为?字符串,
preferredStyle:。警报)
let retryAction=UIAlertAction(标题:“重试”,样式:。默认,处理程序:nil)
alertController.addAction(retryAction)
self.present(alertController,动画:true,完成:nil)
}否则{
self.usernameTextField.text=nil
self.disclose(动画:true,完成:nil)
}
}
}