我正在尝试学习如何在我的iphone app后端使用名为quickblox的服务。我在验证我的应用程序与quickblox服务的连接时遇到了问题。为了授权连接,我需要通过发送包含我的app id,auth_key,timestamp,nonce和签名的post请求从quickblox获取令牌。但是,当我发送帖子请求时,服务器回复状态码422,表明我的签名无效。签名是通过获取app id,auth key,timestamp和nonce并使用它生成hmac-sha1哈希来完成的。我已经验证我的hmac-sha1生成器工作正常,所以我不知道我的邮政编码是否错误或是否是其他东西,因为它总是带回签名错误。这是我的应用代表:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
int nonce = arc4random() % (999999999 - 100000) + 100000;
int timestamp = [[NSDate date] timeIntervalSince1970];
NSString *prehash = [NSString stringWithFormat:@"application_id=999&auth_key=999999999999999×tamp=%i&nonce=%i", timestamp, nonce];
HashSHA256 * hashSHA256 = [[HashSHA256 alloc] init];
NSString * hash = [hashSHA256 hashedValue:prehash];
NSLog(@"%@", hash);
[application setIdleTimerDisabled:YES];
//
// Set QuickBlox credentials. Register at admin.quickblox.com, create a new app
// and copy credentials here to have your own backend instance enabled.
[QBSettings setApplicationID:9999];
[QBSettings setAuthorizationKey:@"999999999999999"];
[QBSettings setAuthorizationSecret:@"111111111111111"];
NSString *urlString = [NSString stringWithFormat:@"http://api.quickblox.com/session.xml"];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
//set headers
NSString *contentType = [NSString stringWithFormat:@"0.1.0"];
[request addValue:contentType forHTTPHeaderField: @"QuickBlox-REST-API-Version:"];
//create the body
NSMutableData *postBody = [NSMutableData data];
[postBody appendData:[[NSString stringWithFormat:@"application_id=9999&auth_key=999999999999999×tamp=%i&nonce=%i&signature=%@", timestamp, nonce, hash] dataUsingEncoding:NSUTF8StringEncoding]];
//post request
[request setHTTPBody:postBody];
NSString *a = [[NSString alloc] initWithData:postBody encoding:NSUTF8StringEncoding];
NSLog(@"%@", a);
//get response
NSHTTPURLResponse* urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(@"Response Code: %d", [urlResponse statusCode]);
if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 500) {
NSLog(@"Response: %@", result);
//here you get the response
}
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.backgroundColor = [UIColor whiteColor];
// Show Splash screen
//
SplashViewController *splashViewController = [[SplashViewController alloc] init];
[self.window setRootViewController:splashViewController];
[splashViewController release];
[self.window makeKeyAndVisible];
return YES;
}
文档说请求的格式应该是这样的。 有没有人看到帖子请求有问题,我没有正确格式化吗?文档说它的格式应该是这样的:
curl -X POST \
-H "QuickBlox-REST-API-Version: 0.1.0" \
-d "application_id=140&auth_key=7quWEh-k6TqghXe×tamp=1326964049&nonce=414546828&signature=e6e603c251a569e70a2f27a8c71b5017e81e05d5" \
https://api.quickblox.com/session.xml //sent to this address
提前致谢。
答案 0 :(得分:1)
看起来你错过了你的auth_secret。它应该用于生成签名。这是python示例,它对您有用。
import time, random, hmac, urllib, httplib
from hashlib import sha1
nonce = str(random.randint(1, 10000))
timestamp = str(int(time.time()))
signature_raw_body = ("application_id=" + application_id + "&auth_key=" + auth_key +
"&nonce=" + nonce + "×tamp=" + timestamp)
signature = hmac.new(auth_secret, signature_raw_body, sha1).hexdigest()
params = urllib.urlencode({'application_id': application_id,
'auth_key': auth_key,
'timestamp': timestamp, 'nonce' : nonce,
'signature' : signature})
conn = httplib.HTTPSConnection("api.quickblox.com")
conn.request("POST", "/session", params, {})
response = conn.getresponse()
您也可以使用此方法生成签名:
+ (NSString *)signData:(NSData *)data withSecret:(NSString *)secret{
NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *clearTextData = data;
uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
CCHmacContext hmacContext;
CCHmacInit(&hmacContext, kCCHmacAlgSHA1, secretData.bytes, secretData.length);
CCHmacUpdate(&hmacContext, clearTextData.bytes, clearTextData.length);
CCHmacFinal(&hmacContext, digest);
NSData *result = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
NSString *hash = [result description];
hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""];
hash = [hash stringByReplacingOccurrencesOfString:@"<" withString:@""];
hash = [hash stringByReplacingOccurrencesOfString:@">" withString:@""];
return hash;
}
其中:
#define CC_SHA1_DIGEST_LENGTH 20
NSData *数据是使用NSUTF8StringEncoding的原始数据。