使用Amazon Cognito iOS首次API调用返回403问题求助
解决Amazon Cognito认证后API调用立即返回403的问题
从你给出的错误信息来看,问题非常明确:刚完成Cognito认证后发起的API调用,使用的是未授权(unauth)角色的凭证,而非认证后的授权(auth)角色凭证——这也是重启App后调用正常的原因:重启时AWSMobileClient会自动加载缓存的登录状态,刷新并获取到正确的授权角色凭证。
问题根源
你在user.getSession()的成功回调里立刻发起API调用,但此时AWSMobileClient还没来得及完成凭证的刷新和角色切换,依然在使用之前的未授权角色凭证,导致API网关拒绝请求。
解决方案
你需要确保在凭证完全切换到授权角色之后再发起API调用,这里有两种可靠的实现方式:
方式1:登录成功后手动刷新凭证
在getSession成功后,调用凭证提供者的refresh()方法,等待刷新完成再执行API调用:
let user = pool.currentUser() ?? pool.getUser() user.getSession("myUsername", password: "myPassword", validationData: nil).continueOnSuccessWith { sessiontask -> Any? in // 手动刷新凭证,确保切换到授权角色 self.credentialsProvider.refresh().continueWith { refreshTask in guard refreshTask.error == nil else { // 处理凭证刷新错误 return nil } // 现在凭证已更新,可以安全发起API调用 let request = AWSAPIGatewayRequest(httpMethod: "POST", urlString: "/my-api-endpoint", queryParameters: nil, headerParameters: nil, httpBody: nil) let serviceClient = AWSAPI_MY_AUTOGENERATED_Client.default() return serviceClient.invoke(request).continueOnSuccessWith(block: { (task) -> Any? in if let result = task.result, result.statusCode == 200 { // A: 一切正常 - 继续执行 } else { // B: 处理错误(如403等) } return nil }) } return nil }
方式2:使用AWSMobileClient的状态监听(更推荐)
直接使用AWSMobileClient的登录方法,并监听其状态变化,当状态变为signedIn时,说明凭证已准备就绪:
首先,修改你的认证代码:
// 在视图控制器的合适位置(比如viewDidLoad)添加状态监听 AWSMobileClient.sharedInstance().addStateChangeObserver(self) { [weak self] state, error in guard let self = self else { return } switch state { case .signedIn: // 用户已登录且凭证已切换到授权角色,发起API调用 self.makeAuthorizedAPICall() default: break } } // 发起登录请求 AWSMobileClient.sharedInstance().signIn(username: "myUsername", password: "myPassword") { result, error in guard error == nil else { // 处理登录失败 print("登录错误:\(error!.localizedDescription)") return } // 登录成功后,等待状态监听触发signedIn事件 } // 封装API调用方法 private func makeAuthorizedAPICall() { let request = AWSAPIGatewayRequest(httpMethod: "POST", urlString: "/my-api-endpoint", queryParameters: nil, headerParameters: nil, httpBody: nil) let serviceClient = AWSAPI_MY_AUTOGENERATED_Client.default() serviceClient.invoke(request).continueOnSuccessWith(block: { (task) -> Any? in if let result = task.result, result.statusCode == 200 { // A: 一切正常 - 继续执行 } else { // B: 处理错误(如403等) } return nil }) }
额外注意事项
- 你的AppDelegate配置是正确的,
AWSMobileClient.sharedInstance().interceptApplication已经帮你处理了基础的初始化逻辑,不需要改动。 - 尽量避免直接操作
AWSCognitoIdentityUserPool的getSession,而是使用AWSMobileClient的登录方法,它会更可靠地管理凭证生命周期和角色切换。
内容的提问来源于stack exchange,提问作者lihamuki
相关产品推荐
相关产品推荐

