【问题标题】:AWS iOS SDK Cognito Developer Authentication (Swift)AWS iOS SDK Cognito 开发人员身份验证 (Swift)
【发布时间】:2015-04-15 04:23:33
【问题描述】:

我很难弄清楚如何将我的服务器(通过 AWS)提供的开发人员凭据返回给我的示例身份提供商。

看来我需要在 ExampleIdentityProvider 类的 refresh 方法中同步执行此操作。我正在使用 AFNetworking 发出请求,但它是异步 GET 请求。如何为我的 IdentityProvider 上的刷新方法同步执行此操作?

以下是在 Swift 中的:

class ExampleIdentityProvider: AWSAbstractIdentityProvider  {
    var newToken: String!

    override var token: String {
        get {
            return newToken
        }
        set {
            newToken = newValue
        }
    }

    override func getIdentityId() -> BFTask! {
        if self.identityId != nil {
            return BFTask(result: self.identityId)
        }else{
            return BFTask(result: nil).continueWithBlock({ (task) -> AnyObject! in
                if self.identityId == nil {
                    return self.refresh()
                }
                return BFTask(result: self.identityId)
            })
        }
    }

    override func refresh() -> BFTask! {
        return BFTask(result: nil).continueWithBlock({ (task) -> AnyObject! in
            let result =  AFNETWORKING REQUEST FOR CREDENTIALS TO MY SERVER
            self.identityId = result.identityId
            self.token = result.token

            return BFTask(result: self.identityId)
        })
    }
}

【问题讨论】:

    标签: ios amazon-web-services aws-sdk amazon-cognito aws-sdk-ios


    【解决方案1】:

    我相信我已经弄明白了。我需要使用 BFTask,它是为处理后台任务而构建的。

    对于那些在使用 Cognito 进行开发人员身份验证的 Swift 实现中苦苦挣扎的人,他们可能与我有类似的设置,这就是我完成它的方式:

    class ExampleAppIdentityProvider: AWSAbstractCognitoIdentityProvider {
        var _token: String!
        var _logins: [ NSObject : AnyObject ]!
    
        // Header stuff you may not need but I use for auth with my server
        let acceptHeader = "application/vnd.exampleapp-api+json;version=1;"
        let authHeader = "Token token="
        let userDefaults = NSUserDefaults.standardUserDefaults()
        let authToken = self.userDefaults.valueForKey("authentication_token") as String
    
        // End point that my server gives amazon identityId and tokens to authorized users
        let url = "https://api.myapp.com/api/amazon_id/"
    
        override var token: String {
            get {
                return _token
            }
        }
    
        override var logins: [ NSObject : AnyObject ]! {
            get {
                return _logins
            }
            set {
                _logins = newValue
            }
        }
    
        override func getIdentityId() -> BFTask! {
            if self.identityId != nil {
                return BFTask(result: self.identityId)
            }else{
                return BFTask(result: nil).continueWithBlock({ (task) -> AnyObject! in
                    if self.identityId == nil {
                        return self.refresh()
                    }
                    return BFTask(result: self.identityId)
                })
            }
        }
    
        override func refresh() -> BFTask! {
            let task = BFTaskCompletionSource()
            let request = AFHTTPRequestOperationManager()
            request.requestSerializer.setValue(self.acceptHeader, forHTTPHeaderField: "ACCEPT")
            request.requestSerializer.setValue(self.authHeader+authToken, forHTTPHeaderField: "AUTHORIZATION")
            request.GET(self.url, parameters: nil, success: { (request: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
                // The following 3 lines are required as referenced here: http://stackoverflow.com/a/26741208/535363
                var tmp = NSMutableDictionary()
                tmp.setObject("temp", forKey: "ExampleApp")
                self.logins = tmp
    
                // Get the properties from my server response
                let properties: NSDictionary = response.objectForKey("properties") as NSDictionary
                let amazonId = properties.objectForKey("amazon_identity") as String
                let amazonToken = properties.objectForKey("token") as String
    
                // Set the identityId and token for the ExampleAppIdentityProvider
                self.identityId = amazonId
                self._token = amazonToken
    
                task.setResult(response)
            }, failure: { (request: AFHTTPRequestOperation!, error: NSError!) -> Void in
                task.setError(error)
            })
            return task.task
        }
    }
    

    并通过以下方式初始化ExampleAppIdentityProvider

        let identityProvider = ExampleAppIdentityProvider()
        let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityProvider: identityProvider, unauthRoleArn: GlobalVariables.cognitoUnauthRoleArn, authRoleArn: GlobalVariables.cognitoAuthRoleArn)
        let defaultServiceConfiguration = AWSServiceConfiguration(region: .USEast1, credentialsProvider: credentialsProvider)
        AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration
    
        let transferManager = AWSS3TransferManager.defaultS3TransferManager()
    
        let uploadRequest = AWSS3TransferManagerUploadRequest()
        uploadRequest.bucket = GlobalVariables.awsBucket
        uploadRequest.key = "\(GlobalVariables.environment)/uploads/users/\(userId)/\(type)/\(timestamp)/original.jpg"
        uploadRequest.ACL = .AuthenticatedRead
        uploadRequest.body = tmpFileUrl
    
        // Upload file
        let task = transferManager.upload(uploadRequest)
    

    我创建了一个名为 GlobalVariablesstruct,其中包含保存 bucketunAuthRoleArnauthRoleArn 等值的全局环境变量。当然你不必这样做,但我提及它以防有人感到困惑。

    【讨论】:

    • 您能展示一下您是如何初始化提供程序/配置以供 AWS 使用的吗?
    • @user871177 查看上面的更新代码。希望对您有所帮助。
    • 能不能不用 AWSTask 来代替单独导入 Bolts 框架?
    • @JBaczuk 这是在亚马逊将 AWSTask 包含在此框架中之前编写的,而是使用 BFTask。您现在当然可以使用 AWSTask。
    • 当你设置的登录映射值是“temp”任意?即使我成功获得令牌并设置登录映射,我似乎也无法获得经过身份验证的身份。 (docs.aws.amazon.com/cognito/devguide/identity/…)
    【解决方案2】:

    您可以为 cognito 身份验证生成自定义类

    import AWSS3
    import AWSCore
    import Alamofire
    
    //This variable is store aws credential token
    var cachedLogin : NSDictionary?
    final class AmazonIdentityProvider : AWSCognitoCredentialsProviderHelper{
    
        // Handles getting the login
        override func logins() -> AWSTask<NSDictionary> {
            guard let cachedLoginObj = cachedLogin else {
                return getCredentials().continueWith(block: { (credentialTask) -> AWSTask<NSDictionary> in
                    guard let credential = credentialTask.result else {
                        return AWSTask(result: nil)
                    }
    
                    self.setCognitoTokenKey(credential: credential)
    
                    return AWSTask(result: cachedLogin)
                }) as! AWSTask<NSDictionary>
            }
            return AWSTask(result: cachedLoginObj)
        }
    
        // Handles getting a token from the server
        override func token() -> AWSTask<NSString> {
            return getCredentials().continueWith(block: { (credentialTask) -> AWSTask<NSString> in
                guard let credential = credentialTask.result else {
                    return AWSTask(result: nil)
                }
    
                self.setCognitoTokenKey(credential: credential)
    
                return AWSTask(result: credential.token as NSString)
            }) as! AWSTask<NSString>
        }
    
        // Handles getting the identity id
        override func getIdentityId() -> AWSTask<NSString> {
    
            return getCredentials().continueWith(block: { (credentialTask) -> AWSTask<NSString> in
                guard let credential = credentialTask.result else {
                    return AWSTask(result: nil)
                }
    
                self.setCognitoTokenKey(credential: credential)
    
                return AWSTask(result: credential.identityId as NSString)
            }) as! AWSTask<NSString>
        }
    
        //This method is used to AWS Token set
        func setCognitoTokenKey(credential : AmazonCognitoCredential){
            let login: NSDictionary = ["cognito-identity.amazonaws.com": credential.token]
            cachedLogin = login
            self.identityId = credential.identityId
        }
    
        // Gets credentials from server
        func getCredentials() -> AWSTask<AmazonCognitoCredential> {
            let tokenRequest = AWSTaskCompletionSource<AmazonCognitoCredential>()
            getAwsToken { (isSuccess, error, credentials) in
                if isSuccess
                {
                    tokenRequest.set(result: credentials)
                }
                else
                {
                    tokenRequest.set(error: error!)
                }
            }
            return tokenRequest.task
        }
        typealias CompletionBlock = (_ success:Bool,_ errorMassage:Error?,_ responce:AmazonCognitoCredential?) -> Void
        func getAwsToken(complitionBlock : @escaping CompletionBlock)  {
    //Your server token code
    }
    /// AmazonCognito credential custom class
    final class AmazonCognitoCredential {
        let token: String
        let identityId: String
    
        init(token: String, identityId: String) {
            self.token = token
            self.identityId = identityId
        }
    }
    

    你可以在应用委托中使用

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
        AWSDDLog.sharedInstance.logLevel = .all
        let identityProvider = AmazonIdentityProvider()
        let credentialsProvider = AWSCognitoCredentialsProvider(regionType: .USEast1, unauthRoleArn: CognitoRoleUnauth, authRoleArn: CognitoRoleAuth, identityProvider: identityProvider)
        let configuration = AWSServiceConfiguration(region: .USWest2, credentialsProvider: credentialsProvider)
        AWSServiceManager.default().defaultServiceConfiguration = configuration
    
        let task = identityProvider.getIdentityId()
        task.continueWith { (task:AWSTask) -> Any? in
            if (task.error != nil ) {
                print("\(String(describing: task.error))")
            } else {
                print("Task result: \(String(describing: task.result))")
            }
            return nil
        }
        return true
    }
    

    【讨论】:

      【解决方案3】:

      首先要将文件、图像、视频上传到 AWS S3 privet 存储桶,您需要为您需要的 ('CognitoId, 进行 AWS 身份验证 >CognitoAccesstoken),您从后端服务器获得。您应该具有“CognitoPoolID”、“S3 存储桶名称”和“Region >' 您可以将其保存在 swift 代码中的常量文件中。 之后,您必须为 AWS 身份验证编写 单独的类

      import UIKit
      import AWSCore
      // this custom class is dedicated for getting getting aws dev auth identity credentials
      class DeveloperAuthenticatedIdentityProvider: AWSCognitoCredentialsProviderHelper {
          override init(regionType: AWSRegionType, identityPoolId: String, useEnhancedFlow: Bool, identityProviderManager: AWSIdentityProviderManager?) {
              super.init(regionType: regionType, identityPoolId: identityPoolId, useEnhancedFlow: useEnhancedFlow, identityProviderManager: identityProviderManager)
          }
          override func token() -> AWSTask<NSString> {
              self.identityId = “ADD_COGNITO_IDENTITY_ID”
              let token = “ADD_COGNITO_ACCESS_TOKEN”
              return AWSTask(result: token )
          }
          override func logins () -> AWSTask<NSDictionary> {
              return super.logins()
          }
          /*
           * Use the refresh method to communicate with your backend to get an
           * identityId and token.
           */
          func refresh() -> AWSTask<NSString> {
              self.identityId = “ADD_COGNITO_IDENTITY_ID”
              return AWSTask(result: identityID)
          }
      }     
      

      //从您上传文件的类中编写以下代码

      let devAuth = DeveloperAuthenticatedIdentityProvider.init(
          regionType: ADD_REGION,
                      identityPoolId:”ADD_COGNITO_POOL_ID”,
                                  useEnhancedFlow: true,
                                              identityProviderManager: nil)
      let credentialsProvider = AWSCognitoCredentialsProvider.init(regionType:”ADD_REGION”, identityProvider: devAuth)
      let configuration = AWSServiceConfiguration.init(region:”ADD_REGION”, credentialsProvider: credentialsProvider)
      AWSServiceManager.default().defaultServiceConfiguration = configuration
      
      
      @IBAction func uplaodVideo(){
          uploadFile(with: "FILE_NAME", type: "mov")
      }
      func uploadFile(with resource: String, type: String) {
              let key = "\(resource).\(type)"
              let localImagePath = Bundle.main.path(forResource: resource, ofType: type)
              let localImageUrl = URL(fileURLWithPath: localImagePath!)
              let transferManager1 = AWSS3TransferUtility.default()
              let expression = AWSS3TransferUtilityUploadExpression()
              self.uploadCompletionHandler = { (task, error) -> Void in
                  DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
                      if ((error) != nil){
                          print("Failed with error")
                          print("Error: \(error!)");
                      }
                      else{
                          print("Sucess")
                      }
                  })
              }
              let transferUtility = AWSS3TransferUtility.default()
              transferUtility.uploadFile(localImageUrl, bucket: "", key: key, contentType: "video/mov", expression: expression, completionHandler: uploadCompletionHandler).continueWith { (task) -> AnyObject? in
                  if let error = task.error {
                      print("Error: \(error.localizedDescription)")
                  }
                  if let _ = task.result {
                      print("Upload Starting!")
                  }
                  return nil;
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-05
        • 2018-12-08
        • 1970-01-01
        • 2016-06-29
        • 2016-01-16
        • 2016-12-11
        • 2015-05-10
        • 2015-01-05
        相关资源
        最近更新 更多