iOS应用AWS Cognito用户池迁移及Lambda触发与认证实现问题
解决Cognito用户迁移触发器在iOS登录时不触发的问题
我之前也碰到过一模一样的情况:Lambda测试正常,但iOS端登录就是不触发迁移触发器。问题根源在于Cognito默认使用的SRP(Secure Remote Password)认证流程不会触发用户迁移——因为SRP需要用户先存在于新用户池中才能完成密钥交换,而迁移触发器是在用户不存在时才会被调用。要触发迁移,必须改用USER_PASSWORD_AUTH认证流程,下面是具体的实现步骤:
第一步:开启用户池App客户端的USER_PASSWORD_AUTH流程
先在AWS控制台确认你的新用户池App客户端已经启用了该流程:
- 进入Cognito用户池 → 选择你的新用户池 → 点击"App客户端"
- 找到对应的App客户端,点击"显示详情"
- 在"认证流程"部分,勾选
USER_PASSWORD_AUTH(如果没勾选的话)
第二步:修改iOS端的Cognito配置,指定使用USER_PASSWORD_AUTH
关键是在初始化用户池时,将allowedAuthFlows设置为包含.userPasswordAuth,告诉SDK使用非SRP的用户名密码认证流程。
完整的代码示例
import AWSCognitoIdentityProvider class AuthManager: NSObject, AWSCognitoIdentityPasswordAuthentication { var currentUsername: String? var currentPassword: String? private var passwordCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>? static let shared = AuthManager() private override init() { super.init() // 替换成你的用户池信息 let poolId = "us-east-1_XXXXXXXXX" let clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXX" let clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXX" // 没有客户端密钥就传nil // 初始化用户池配置 let poolConfig = AWSCognitoIdentityUserPoolConfiguration( clientId: clientId, clientSecret: clientSecret, poolId: poolId, endpoint: nil, region: .USEast1 // 替换成你的AWS区域 ) // 核心设置:指定使用USER_PASSWORD_AUTH流程 poolConfig.allowedAuthFlows = [.userPasswordAuth] // 注册用户池 let userPool = AWSCognitoIdentityUserPool(forKey: "MyAppUserPool", configuration: poolConfig) AWSCognitoIdentityUserPool.register(userPool, forKey: "MyAppUserPool") } // 实现AWSCognitoIdentityPasswordAuthentication协议方法 func getDetails(_ authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput, passwordAuthenticationCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>) { self.passwordCompletionSource = passwordAuthenticationCompletionSource // 这里用你之前获取的用户名密码生成认证详情 guard let username = currentUsername, let password = currentPassword else { passwordAuthenticationCompletionSource.set(error: NSError(domain: "AuthError", code: -1, userInfo: [NSLocalizedDescriptionKey: "用户名或密码为空"])) return } let authDetails = AWSCognitoIdentityPasswordAuthenticationDetails(username: username, password: password) passwordAuthenticationCompletionSource.set(result: authDetails) } func didCompleteStepWithError(_ error: Error?) { // 处理认证过程中的错误 if let error = error { print("认证步骤错误: \(error.localizedDescription)") } } // 对外暴露的登录方法 func login(username: String, password: String, completion: @escaping (Bool, Error?) -> Void) { currentUsername = username currentPassword = password let userPool = AWSCognitoIdentityUserPool(forKey: "MyAppUserPool") let user = userPool.getUser(username) // 发起认证请求 user.authenticateUser(password, passwordAuthenticationCompletion: { (session, error) in if let error = error { completion(false, error) } else if session != nil { completion(true, nil) } else { completion(false, NSError(domain: "AuthError", code: -2, userInfo: [NSLocalizedDescriptionKey: "登录失败,未获取到会话"])) } }) } }
关键说明
allowedAuthFlows的设置是核心:这会强制SDK使用USER_PASSWORD_AUTH流程,直接将用户名密码发送到Cognito,此时如果用户在新池中不存在,就会触发你配置的迁移Lambda触发器。- 如果你之前用的是SRP流程,修改后不需要大幅改动原有代码,只需要调整用户池配置即可。
- 注意:
USER_PASSWORD_AUTH的安全性比SRP低,所以当所有旧用户迁移完成后,建议改回SRP流程(将allowedAuthFlows改回.srp)。
内容的提问来源于stack exchange,提问作者Ankit
相关产品推荐
相关产品推荐

