问题
I try to use google data api and met difficulty at OAuthGetRequestToken. I follow the instruction: requestToken
I use GET and add query parameters after the url.
I create the base string for signature in this way: GET&request url &query parameters(without oauth_signature) ordered by alphabetically
As I use HMAC-SHA1, I use the "consumer secret" value to create the signature.
Finally, I use the url+query parameters, and the browser always returns : signature_invalid base_string:GET&https%3A%2******
and I found the base_string is the same as the one in my code.
I don't know where is the problem and ask for help. Below is my code: (hmac_sha1 is right as I use sample data from Oauth to test)
#import "ContactTestViewController.h"
#import "ASIHTTPRequest.h"
#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonCryptor.h>
#import "Base64.h"
#import "NSStringAdditions.h"
#import "NSData+Base64.h"
#define kAllContacts @"https://www.google.com/m8/feeds/contacts/default/full"
#define kOauthGetRequestToken @"https://www.google.com/accounts/OAuthGetRequestToken"
#define kOauthConsumerKey @"oauth_consumer_key=***.net"
#define kOauthConsumerSecret @"****/*****"
#define kOauthNonce @"oauth_nonce=457261624861626265724761686176"
#define kOauthSigMethod @"oauth_signature_method=HMAC-SHA1"
#define kOauthSignature @"oauth_signature="
#define kOauthTimeStamp @"oauth_timestamp="
#define kOauthScope @"scope=https://www.google.com/m8/feeds/contacts/default/full"
#define kOauthCallback @"oauth_callback=http://****.net/index.html"
#define kOauthVersion @"oauth_version=1.0"
#define kXOauthDisplayname @""
@implementation ContactTestViewController
- (NSString *)parameterStrNoSignature
{
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInter = [currentDate timeIntervalSince1970];
NSString *str = [NSString stringWithFormat:@"%@&%@&%@&%@&%@%d&%@",
kOauthCallback,
kOauthConsumerKey,
kOauthNonce,
kOauthSigMethod,
kOauthTimeStamp,
(int)timeInter,
kOauthScope
];
return str;
}
- (NSString *)hostEncode:(NSString *)str
{
NSString *str1 = [str stringByReplacingOccurrencesOfString:@":" withString:@"%3A"];
NSString *str2 = [str1 stringByReplacingOccurrencesOfString:@"/" withString:@"%2F"];
return str2;
}
- (NSString *)parameterEncode:(NSString *)str
{
NSString *str1 = [str stringByReplacingOccurrencesOfString:@"/" withString:@"%252F"];
NSString *str2 = [str1 stringByReplacingOccurrencesOfString:@":" withString:@"%253A"];
NSString *str3 = [str2 stringByReplacingOccurrencesOfString:@"&" withString:@"%26"];
NSString *str4 = [str3 stringByReplacingOccurrencesOfString:@"=" withString:@"%3D"];
return str4;
}
- (NSString *)hmac_sha1:(NSString *)key text:(NSString*)plainText
{
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [plainText cStringUsingEncoding:NSASCIIStringEncoding];
char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:CC_SHA1_DIGEST_LENGTH];
NSString *hash = [Base64 encode:HMAC];//base64
hash = [HMAC base64EncodedString];
[HMAC release];
return hash;
}
- (void)authTest
{
NSString *parameterNoSignature = [self parameterStrNoSignature];
NSLog(@"no signature parameters:\n%@",parameterNoSignature);
NSString *baseStringEncode = [NSString stringWithFormat: @"GET&%@&%@",
[self hostEncode:kOauthGetRequestToken],
[self parameterEncode:parameterNoSignature]
];
NSLog(@"base string encode:\n%@",baseStringEncode);
NSString *signatureStr = [self hmac_sha1:kOauthConsumerSecret
text:baseStringEncode];
NSLog(@"signature:\n%@",signatureStr);
NSString *urlStr = [NSString stringWithFormat:@"%@?%@&%@%@",
kOauthGetRequestToken,
parameterNoSignature,
kOauthSignature,
signatureStr
];
NSLog(@"url string:\n%@",urlStr);
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
[self authTest];
}
- (void)dealloc {
[super dealloc];
}
回答1:
For the key, you need [in pseudocode]: urlencode(utf8(oauth_consumer_secret)) + "&" + urlencode(utf8(oauth_token_secret))
Just using the oauth_consumer_secret is insufficient. If oauth_token_secret is empty, as it will be at the beginning of the OAuth process, that part will be empty but you still need the & following the encoded consumer secret.
来源:https://stackoverflow.com/questions/5674405/oauthgetrequesttokensignature-invalid-error