问题
I am trying to learn how to use a service called quickblox for my iphone app backend. I have run into a problem when validating my app's connection with the quickblox service though. In order to authorize the connection I need to get a token from quickblox by sending a post request that contains my app id, auth_key, timestamp, a nonce, and a signature. When I send the post request however, the server replies back with status code 422 that my signature is invalid. The signature is made by taking the app id, auth key, timestamp, and nonce and generating a hmac-sha1 hash with it. I have verified that my hmac-sha1 generator is working correctly, so I don't know if my post code is wrong or whether it's something else, because it always comes back with signature error. Here is my app delegate:
- (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;
}
The documentation says that the request should be formatted like this. Does anyone see a problem with the post request, am I not formatting it correctly? The documentation says it should be formatted like this:
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
Thanks in advance.
回答1:
Looks like you missed your auth_secret. It should be used in generating signature. Here is python example, it can be useful for you.
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()
Also you can use this method for generating signature:
+ (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;
}
Where:
#define CC_SHA1_DIGEST_LENGTH 20
NSData *data is data from raw body using NSUTF8StringEncoding.
来源:https://stackoverflow.com/questions/17541616/invalid-signature-error-when-sending-an-authorization-request-to-quickblox-via-p