AWS iOS SDK Cognito 开发人员身份验证 (Swift)
AWS iOS SDK Cognito Developer Authentication (Swift)
我很难弄清楚如何 return 我的服务器(通过 AWS)向我的示例身份提供商提供的开发人员凭据。
看来我需要在 ExampleIdentityProvider class 的 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)
})
}
}
我相信我已经弄明白了。我需要利用 BFTask,它是为处理后台任务而构建的。
对于那些努力 Swift 使用 Cognito 实施开发人员身份验证的人,他们可能与我有类似的设置,这就是我完成它的方式:
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:
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
等值的全局环境变量。当然你不必这样做,但我会提到它以防有人感到困惑。
您可以为 Cognito 身份验证生成自定义 class
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
}
首先要将文件、图像、视频上传到 AWS S3 privet 存储桶,您需要为您需要的 ('CognitoId , CognitoAccesstoken) 你从后端得到的-server.You 应该有 'CognitoPoolID', 'S3 bucket name' 和 'Region' 可以保存在 swift 代码内的常量文件中。
之后你必须为 AWS Authentication
编写 separate class
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)
}
}
//从 class 上传文件
的地方写下代码
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;
}
}
我很难弄清楚如何 return 我的服务器(通过 AWS)向我的示例身份提供商提供的开发人员凭据。
看来我需要在 ExampleIdentityProvider class 的 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)
})
}
}
我相信我已经弄明白了。我需要利用 BFTask,它是为处理后台任务而构建的。
对于那些努力 Swift 使用 Cognito 实施开发人员身份验证的人,他们可能与我有类似的设置,这就是我完成它的方式:
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:
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
等值的全局环境变量。当然你不必这样做,但我会提到它以防有人感到困惑。
您可以为 Cognito 身份验证生成自定义 class
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
}
首先要将文件、图像、视频上传到 AWS S3 privet 存储桶,您需要为您需要的 ('CognitoId , CognitoAccesstoken) 你从后端得到的-server.You 应该有 'CognitoPoolID', 'S3 bucket name' 和 'Region' 可以保存在 swift 代码内的常量文件中。 之后你必须为 AWS Authentication
编写 separate classimport 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)
}
}
//从 class 上传文件
的地方写下代码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;
}
}