2016-06-22 23 views
2

AWS(亞馬遜網絡服務)的文檔非常龐大,而且相當混亂。我發現了一個iOS版的git repo,演示了執行各種任務,包括將數據傳遞給S3的一些項目。使用授權從Amazon S3執行HTTP GET的最小iOS代碼?

我已經有一個現有的客戶端應用程序,它使用Apples NSURLSession在記錄公開時爲來自S3的內容執行HTTPS GET請求。但是,我的客戶希望數據安全。

我不想花時間學習AWSS3TransferManager框架,我也不想將整個框架包含在我的項目中)。我不想要那麼多的行李。我所需要的只是一個調用,它允許我提供用戶標識或訪問密鑰/密鑰或密碼,並獲得一個查詢字符串,我可以將其添加到我的HTTP請求中,以向所有用戶授予請求。

我不需要上傳。我不需要基於API的控制檯支持。我不需要或不需要亞馬遜的會話管理器/下載管理器。我所需要的只是1次調用,它可以讓我提供一個訪問密鑰和密鑰,並返回可以添加到獲得授權的get請求的內容,以便我可以提交請求並獲取文件。應該很簡單吧?我一直在通過文檔和示例代碼幾個小時,現在沒有運氣。

看樣品,他們使用我不需要和不想要的500公斤框架。

有人可以指向一個最小的庫,讓我生成密鑰(s)我需要證明用戶有權訪問此內容,給定用戶名和訪問密鑰ID和密鑰,或者密碼?這不會很難。

+0

有人用64K代表應該知道不要問的好開始的問題「有人可以點我到最小庫「 – miken32

回答

1

這樣做的一個問題是,它聽起來像是在試圖將密鑰/訪問密鑰嵌入到應用程序本身中,而不是使用iOS SDK提供訪問的Amazon Cognito https://aws.amazon.com/cognito/等更安全的內容。

另一個問題是,適用於AWS的iOS SDK不允許您選擇包含哪些方法,儘管它允許您爲S3獲取預生成的URL。對於S3而言,您只需要S3 &核心框架,但聽起來好像太多了。

如果您真的只想要儘可能最小的下載大小,您可以通過查看AWS iOS SDK源代碼https://github.com/aws/aws-sdk-ios或S3的簽名文檔來實現AWS簽署,但簽署AWS請求並不重要,很多有益的邏輯(重試,等等)。

你也提到不想學習TransferManager。 TransferUtility是它的繼承者,並且比實現自己的簽名要快得多。我無法瞭解它需要一兩個多小時才能理解它(如果您決定使用Cognito進行身份驗證,那麼可能會稍微多一點,但這與TransferUtility真的很相似)。 http://docs.aws.amazon.com/mobile/sdkforios/developerguide/s3transferutility.html

編輯:爲PreSignedURLBuilder提供憑據。您還可以看到在http://docs.aws.amazon.com/mobile/sdkforios/developerguide/setup.html添加憑據與SDK創建的所有客戶端(入門斯威夫特/ Objective-C的部分)

您可以使用此提供憑據

AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] 
                 initWithRegionType:AWSRegionUSEast1 identityPoolId:@"IDENTITY_POOL_ID"]; 
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] 
              initWithRegion:AWSRegionUSEast1 credentialsProvider:credentialsProvider]; 

[AWSS3PreSignedURLBuilder registerS3PreSignedURLBuilderWithConfiguration:configuration 
                    forKey:@"customServiceConfiguration"]; 
AWSS3PreSignedURLBuilder *customPreSignedURLBuilder = [AWSS3PreSignedURLBuilder S3PreSignedURLBuilderForKey:@"customServiceConfiguration"]; 
+0

根據我讀的內容,您可以獲取您的ID和祕密ID,您要請求的URL以及服務器時間戳,並生成簽名字符串,然後可以將其作爲查詢字符串嵌入到請求中。這就是我需要的。但是,描述冗長而繁瑣,而且涉及很多機會,導致一些小錯誤的發生,這些錯誤會阻止它正常工作並且需要大量的調試。的Bleh。 –

+0

我有一個完全編寫的應用程序,使用公共URL獲取S3記錄。它使用'NSURLSession',並且已經處理後臺下載,錯誤恢復等。當你的應用程序被終止時,Apple能夠提供下載。第三方應用程序不能這樣做,除非它們的API構建在「NSURLSession」之上並創建一個下載任務。 –

+0

你說過「......它確實允許你爲S3生成一個預先簽名的URL」。通過它,你的意思是亞馬遜SDK?怎麼樣?這就是我需要做的,儘管我寧願不使用始終有效的靜態URL。在這種情況下,有人可以獲取URL並從其他設備請求,從而完全破壞安全。 –

0

這裏是HTTP簡單的代碼得到。如果您對HTTP PUT感興趣 - 請在http://simpleios.s3-website-us-east-1.amazonaws.com處檢查實施。

#進口< CommonCrypto/CommonCrypto.h>

static NSString * const [email protected]"AKIAIOSFODNN7EXAMPLE"; 
static NSString * const [email protected]"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"; 

...

NSString * [email protected]"https://s3.amazonaws.com/someBucket/someFile"; 
NSString * [email protected]"someBucket"; 
NSString * [email protected]"someFile"; 

NSURLSession *delegateFreeSession=[NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration] delegate: nil delegateQueue: [NSOperationQueue mainQueue]]; 
[[delegateFreeSession dataTaskWithURL: [NSURL URLWithString:[fileUrl stringByAppendingString:[self buildQuery:bucket forFile:filePath]]] completionHandler:^(NSData *received, NSURLResponse *response, NSError *error) { 
if(error!=nil){ 
NSLog(@"Error trying to download file - %@", error); 
} 
else{ 
    //do something 
} 
}] resume ]; 

... 

- (NSString *) buildQuery:(NSString *)bucketName forFile:(NSString *)filePath{ 

NSString *expDate=[self expirationDate]; 

NSMutableString *base=[NSMutableString new]; 
[base appendString:@"?AWSAccessKeyId="]; 
[base appendString:accessKey]; 
[base appendString:@"&Expires="]; 
[base appendString:expDate]; 
[base appendString:@"&Signature="]; 

NSMutableString *stringToSign=[NSMutableString new]; 
[stringToSign appendString:@"GET\n\n\n" ]; 
[stringToSign appendString:expDate]; 
[stringToSign appendString:@"\n" ]; 
[stringToSign appendString:@"/"]; 
[stringToSign appendString:bucketName]; 
[stringToSign appendString:@"/"]; 
[stringToSign appendString:filePath]; 

NSString *signature=[self sign:stringToSign]; 
signature=[signature stringByReplacingOccurrencesOfString:@"/" withString:@"%2F"]; 
signature=[signature stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"]; 
signature=[signature stringByReplacingOccurrencesOfString:@"=" withString:@"%3D"]; 

[base appendString:signature]; 

return base; 
} 

- (NSString *) expirationDate{ 

int expireInSeconds=300; 
double sec=[[NSDate date] timeIntervalSince1970]+expireInSeconds; 
static NSNumberFormatter *numberFormatter=nil; 

if(numberFormatter==nil){ 
numberFormatter=[NSNumberFormatter new]; 
[numberFormatter setMaximumFractionDigits:0]; 
} 

NSString *expDate=[numberFormatter stringFromNumber:[NSNumber numberWithDouble:sec]]; 

return expDate; 
} 

- (NSString *)sign:(NSString *)stringToSign { 

NSData *data=[stringToSign dataUsingEncoding:NSUTF8StringEncoding]; 
CCHmacContext context; 
const char *keyCString = [secretKey cStringUsingEncoding:NSASCIIStringEncoding]; 
CCHmacInit(&context, kCCHmacAlgSHA1, keyCString, strlen(keyCString)); 
CCHmacUpdate(&context, [data bytes], [data length]); 
unsigned char digestRaw[CC_SHA1_DIGEST_LENGTH]; 
NSInteger digestLength = CC_SHA1_DIGEST_LENGTH; 
CCHmacFinal(&context, digestRaw); 
NSData *digestData = [NSData dataWithBytes:digestRaw length:digestLength]; 
return [digestData base64EncodedStringWithOptions:kNilOptions]; 
}