5

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

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

以下是斯威夫特:

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)
        })
    }
}
4

3 回答 3

12

我相信我已经想通了。我需要使用 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)

我创建了一个 带有全局环境变量的struct名称,其中包含、、等的值。当然你不必这样做,但我会提到它以防有人感到困惑。GlobalVariablesbucketunAuthRoleArnauthRoleArn

于 2015-02-14T10:35:49.427 回答
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
}
于 2017-12-12T04:29:14.583 回答
0

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

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;
        }
    }
于 2019-08-10T17:59:37.627 回答