AWS iOS SDK Cognito 开发人员身份验证 (Swift)
Posted
技术标签:
【中文标题】AWS iOS SDK Cognito 开发人员身份验证 (Swift)【英文标题】:AWS iOS SDK Cognito Developer Authentication (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)
)
【问题讨论】:
【参考方案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://***.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)
我创建了一个名为 GlobalVariables
的 struct
,其中包含保存 bucket
、unAuthRoleArn
、authRoleArn
等值的全局环境变量。当然你不必这样做,但我提及它以防有人感到困惑。
【讨论】:
您能展示一下您是如何初始化提供程序/配置以供 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;
【讨论】:
以上是关于AWS iOS SDK Cognito 开发人员身份验证 (Swift)的主要内容,如果未能解决你的问题,请参考以下文章
如何在iOS中使用AWSMobileClient获取AWS Cognito用户属性?
是否可以使用iOS SDK更改Amazon Cognito中的用户名?
什么是用于在 Cognito 中登录的 AWS 开发工具包库(从后端不使用 Amplify)?