You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS集成Amazon Cognito:未登录时跳转启动页而非登录页问题

嘿,这个问题我之前帮人处理过,其实调整起来没那么复杂,核心是把你的启动页接入到Cognito的认证协议流程里,而不是直接返回登录页。给你一步步拆解怎么做:

核心思路

AWSCognitoIdentityInteractiveAuthenticationDelegate要求返回的VC必须遵循AWSCognitoIdentityPasswordAuthentication协议,那我们就让启动页VC来遵循这个协议,把它作为认证流程的入口,再在启动页里处理登录/注册的跳转逻辑,同时把Cognito的认证回调传递给后续的登录/注册页面,完成整个流程。

步骤1:让启动页遵循认证协议

首先给你的启动页VC添加协议遵循,同时实现两个核心协议方法,还要保存Cognito的回调对象:

class LaunchViewController: UIViewController, AWSCognitoIdentityPasswordAuthentication {
    // 保存Cognito的认证回调,登录/注册完成后必须调用它
    var passwordAuthenticationCompletion: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>?
    var lastKnownUsername: String?
    
    // 协议方法:Cognito触发认证时调用,我们在这里跳转到登录页
    func getPasswordAuthenticationDetails(_ authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput, passwordAuthenticationCompletion: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>) {
        self.passwordAuthenticationCompletion = passwordAuthenticationCompletion
        self.lastKnownUsername = authenticationInput.lastKnownUsername
        
        // 跳转到登录VC,把回调和上次的用户名传递过去
        let loginVC = LoginViewController()
        loginVC.authCompletion = passwordAuthenticationCompletion
        loginVC.preFillUsername = lastKnownUsername
        navigationController?.pushViewController(loginVC, animated: true)
    }
    
    // 协议方法:认证步骤完成时调用(处理成功/错误)
    func didCompletePasswordAuthenticationStepWithError(_ error: Error?) {
        if let authError = error {
            // 这里可以在启动页显示认证错误提示,比如弹个Alert
            let alert = UIAlertController(title: "登录失败", message: authError.localizedDescription, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            present(alert, animated: true)
        } else {
            // 认证成功!跳转到你的主页面
            let mainTabBar = MainTabBarController()
            UIApplication.shared.keyWindow?.rootViewController = mainTabBar
        }
    }
    
    // 启动页的登录按钮点击事件
    @IBAction func loginButtonTapped(_ sender: UIButton) {
        // 如果用户主动点登录,直接触发跳转逻辑
        let loginVC = LoginViewController()
        loginVC.authCompletion = passwordAuthenticationCompletion
        loginVC.preFillUsername = lastKnownUsername
        navigationController?.pushViewController(loginVC, animated: true)
    }
    
    // 启动页的注册按钮点击事件
    @IBAction func registerButtonTapped(_ sender: UIButton) {
        let registerVC = RegisterViewController()
        registerVC.onRegisterSuccess = { [weak self] username, password in
            // 注册成功后,手动给Cognito传递认证信息,触发登录流程
            let authDetails = AWSCognitoIdentityPasswordAuthenticationDetails(username: username, password: password)
            self?.passwordAuthenticationCompletion?.set(result: authDetails)
            // 返回启动页,等待Cognito处理结果
            self?.navigationController?.popViewController(animated: true)
        }
        navigationController?.pushViewController(registerVC, animated: true)
    }
}

步骤2:修改AppDelegate的startPasswordAuthentication方法

现在不再返回登录VC,而是返回你的启动页VC,记得如果启动页需要导航的话,包装成导航控制器:

func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let launchVC = storyboard.instantiateViewController(withIdentifier: "LaunchViewController") as! LaunchViewController
    
    // 把启动页嵌入导航控制器,方便后续跳转登录/注册
    let navController = UINavigationController(rootViewController: launchVC)
    UIApplication.shared.keyWindow?.rootViewController = navController
    
    // 注意:返回的是遵循协议的启动页VC,不是导航控制器
    return launchVC
}

步骤3:完善登录VC的逻辑

登录VC需要接收回调和预填用户名,用户输入完成后调用回调告知Cognito:

class LoginViewController: UIViewController {
    var authCompletion: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>?
    var preFillUsername: String?
    
    @IBOutlet weak var usernameField: UITextField!
    @IBOutlet weak var passwordField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 预填上次登录的用户名
        usernameField.text = preFillUsername
    }
    
    @IBAction func confirmLoginTapped(_ sender: UIButton) {
        guard let username = usernameField.text?.trimmingCharacters(in: .whitespaces), !username.isEmpty,
              let password = passwordField.text?.trimmingCharacters(in: .whitespaces), !password.isEmpty else {
            // 提示用户输入完整信息
            let alert = UIAlertController(title: "提示", message: "请输入用户名和密码", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            present(alert, animated: true)
            return
        }
        
        // 把用户输入的信息传递给Cognito
        let authDetails = AWSCognitoIdentityPasswordAuthenticationDetails(username: username, password: password)
        authCompletion?.set(result: authDetails)
        
        // 返回启动页,等待认证结果回调
        navigationController?.popViewController(animated: true)
    }
}

关键注意点

  • 回调对象不能丢:passwordAuthenticationCompletion是连接你的UI和Cognito认证流程的核心,一定要妥善保存,登录/注册完成后必须调用它的set(result:)或set(error:)方法。
  • 注册后的处理:如果用户选择注册,注册成功后需要手动创建AWSCognitoIdentityPasswordAuthenticationDetails并传递给回调,这样Cognito会自动完成后续的登录认证步骤。
  • 错误处理:在didCompletePasswordAuthenticationStepWithError方法里处理认证失败的情况,给用户友好的提示。

这样调整后,当用户未登录时,Cognito会自动跳转到你的启动页,用户可以自由选择登录或注册,整个认证流程也能和Cognito完美对接啦。

内容的提问来源于stack exchange,提问作者Jon Sherman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:59:50