从Swift访问Azure表存储

我想从Swift访问azure色的表格存储。 但是,我试图build立请求,但不能使其工作:

let urlString = "https://<myaccount>.table.core.windows.net/MyTable" let storageUrl = NSURL( string: urlString) let request = NSMutableURLRequest(URL: storageUrl!) //making the date let currentDate = NSDate() let httpFormatter = NSDateFormatter() httpFormatter.timeZone = NSTimeZone(abbreviation: "GMT") httpFormatter.dateFormat = "EEE',' dd MMM yyyy HH':'mm':'ss z" let httpTime = httpFormatter.stringFromDate(currentDate) print(httpTime) let signingString = "GET\n\n\n\(httpTime)\n/<myaccount>/MyTable" print(signingString) let keyString = <myKeyString> let keyData = keyString.dataUsingEncoding(NSUTF8StringEncoding,allowLossyConversion: false)! let signingData = signingString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! let length:Int = Int(CC_SHA256_DIGEST_LENGTH) let hashResult = UnsafeMutablePointer<CUnsignedChar>.alloc(length) CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyData.bytes, Int(keyData.length), signingData.bytes, Int(signingData.length), hashResult) print(hashResult) let hash = NSData(bytes: hashResult, length: Int(CC_SHA256_DIGEST_LENGTH)) let hashString = hash.base64EncodedStringWithOptions(NSDataBase64EncodingOptions([])) hashResult.destroy() //print(hashString) request.setValue("SharedKeyLite <myaccount>:\(hashString)", forHTTPHeaderField: "Authorization") request.setValue("0", forHTTPHeaderField: "Content-Length") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue(httpTime, forHTTPHeaderField: "x-ms-date") request.setValue("", forHTTPHeaderField: "Date") request.HTTPMethod = "GET" NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in if let data = data { let datastring = NSString(data:data, encoding:NSUTF8StringEncoding) print( datastring! ) //print(response) } else { print( error ) } }).resume() 

在下面的正确答案之后,我对String进行了扩展,所以hmac签名非常容易:

 // // CryptoExtensions.swift // LaochTestProject // // Created by Lars Christoffersen on 02/01/16. // Copyright © 2016 Lars Christoffersen. All rights reserved. // import Foundation enum CryptoAlgorithm { case MD5, SHA1, SHA224, SHA256, SHA384, SHA512 var HMACAlgorithm: CCHmacAlgorithm { var result: Int = 0 switch self { case .MD5: result = kCCHmacAlgMD5 case .SHA1: result = kCCHmacAlgSHA1 case .SHA224: result = kCCHmacAlgSHA224 case .SHA256: result = kCCHmacAlgSHA256 case .SHA384: result = kCCHmacAlgSHA384 case .SHA512: result = kCCHmacAlgSHA512 } return CCHmacAlgorithm(result) } var digestLength: Int { var result: Int32 = 0 switch self { case .MD5: result = CC_MD5_DIGEST_LENGTH case .SHA1: result = CC_SHA1_DIGEST_LENGTH case .SHA224: result = CC_SHA224_DIGEST_LENGTH case .SHA256: result = CC_SHA256_DIGEST_LENGTH case .SHA384: result = CC_SHA384_DIGEST_LENGTH case .SHA512: result = CC_SHA512_DIGEST_LENGTH } return Int(result) } } extension String { func hmac(algorithm: CryptoAlgorithm, key: String) -> String { let strData = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! let keyData = NSData(base64EncodedString: key, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)! let digestLen = algorithm.digestLength let hashResult = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen) CCHmac(algorithm.HMACAlgorithm, keyData.bytes, Int(keyData.length), strData.bytes, Int(strData.length), hashResult) let hash = NSData(bytes: hashResult, length: digestLen ) let hashString = hash.base64EncodedStringWithOptions(NSDataBase64EncodingOptions([])) hashResult.destroy() return hashString } } 

终于得到它的工作:)

以下是我的代码,其中列出了Azure存储帐户中的所有表:

 // // main.swift // Azure Storage REST Helper // // Created by Gaurav Mantri on 1/2/16. // import Foundation let accountName = "{account-name}" let urlString = "https://{account-name}.table.core.windows.net/Tables" let storageUrl = NSURL(string: urlString) let request = NSMutableURLRequest(URL: storageUrl!) let currentDate = NSDate() let httpFormatter = NSDateFormatter() httpFormatter.timeZone = NSTimeZone(abbreviation: "GMT") httpFormatter.dateFormat = "EEE',' dd MMM yyyy HH':'mm':'ss z" let httpTime = httpFormatter.stringFromDate(currentDate) print(httpTime) let signingString = "GET\n\n\n\(httpTime)\n/{account-name}/Tables" print(signingString) let keyString = "{account-key}" let keyData = NSData(base64EncodedString: keyString, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)! let signingData = signingString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! let length:Int = Int(CC_SHA256_DIGEST_LENGTH) let hashResult = UnsafeMutablePointer<CUnsignedChar>.alloc(length) CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyData.bytes, Int(keyData.length), signingData.bytes, Int(signingData.length), hashResult) print(hashResult) let hash = NSData(bytes: hashResult, length: Int(CC_SHA256_DIGEST_LENGTH)) let hashString = hash.base64EncodedStringWithOptions(NSDataBase64EncodingOptions([])) hashResult.destroy() print(hashString) request.setValue("SharedKey {account-name}:\(hashString)", forHTTPHeaderField: "Authorization") request.setValue("0", forHTTPHeaderField: "Content-Length") request.setValue(httpTime, forHTTPHeaderField: "x-ms-date") request.setValue("", forHTTPHeaderField: "Date") request.HTTPMethod = "GET" print("comes here") NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in if let data = data { let datastring = NSString(data:data, encoding:NSUTF8StringEncoding) print( datastring! ) print("comes here 1") //print(response) } else { print("comes here 2") print( error ) } }).resume() 

我做了几件事情:

  • 我没有使用UTF8编码来获取keyData ,而是使用base64Encoding创buildNSData
  • 我摆脱了Content-Type标题,所以结果以XML返回。 如果要以JSON格式返回数据,请指定Accept标头而不是Content-Type标头。
  • 您正在使用SharedKeyscheme创build签名,但您在Authorization标头中指定了SharedKeyLite 。 我将其改为SharedKey

哦,请不要判断代码,随意编辑它。 我知道这不是最好的代码:)