关于Sina WeiBo API OAuth 验证(ios)

来源:互联网 发布:辐射四优化补丁 编辑:程序博客网 时间:2024/04/29 03:01

#import<CommonCrypto/CommonHMAC.h>
#import<CommonCrypto/CommonCryptor.h>
#import "Base64.h"

#defineSINA_T_HOST 

                 @"api.t.sina.com.cn"//api.t.sina.com.cn
#defineSINA_WEIBO_APP_KEY           @"YOUR APP KEY"
#defineSECRET                       @"YOUR APP SECRET"
#defineOAUTH_VERSION                @"1.0"
#defineOAUTH_SIGNATURE_METHOD       @"HMAC-SHA1"

#pragma mark 获得时间戳
- (NSString *)_generateTimestamp
{
    return[NSString stringWithFormat:@"%d", time(NULL)];
}

#pragma mark 获得随时字符串 // 这个可以获取随机数,不一定要用uuid的
- (NSString *)_generateNonce
{
    CFUUIDReftheUUID = CFUUIDCreate(NULL);
    CFStringRefstring = CFUUIDCreateString(NULL, theUUID);
   NSMakeCollectable(theUUID);
    return(NSString *)string;
}
#pragma mark 获取request_token的参数
-(void) getRequestToken {
    NSString*baseUrl = [NSStringstringWithFormat:@"http://%@/oauth/request_token",SINA_T_HOST];
    NSString*nonce = [self _generateNonce];
    NSString*timestamp = [self _generateTimestamp];
    
   NSMutableDictionary* info = [NSMutableDictionarydictionaryWithObjectsAndKeys:
                         SINA_WEIBO_APP_KEY,@"oauth_consumer_key",
                                OAUTH_SIGNATURE_METHOD,@"oauth_signature_method",
                                timestamp,@"oauth_timestamp",
                                nonce,@"oauth_nonce",
                                OAUTH_VERSION,@"oauth_version",nil];
    
    [selfhmac_sha1_signature:@"GET" url:baseUrl param:infotoken_secret:@""]; // 获取签名
   ////////////////////
    NSString*oauthHeader = [NSString stringWithFormat:@"OAuth realm="%@",oauth_consumer_key="%@", oauth_signature_method="%@",oauth_signature="%@", oauth_timestamp="%@", oauth_nonce="%@",oauth_version="1.0"",
                            @"",
                            [info valueForKey:@"oauth_consumer_key"],
                            [info valueForKey:@"oauth_signature_method"],
                            [info valueForKey:@"oauth_signature"],
                            [info valueForKey:@"oauth_timestamp"],
                            [info valueForKey:@"oauth_nonce"]];
   ////////////////////
   NSMutableURLRequest *theRequest =[NSMutableURLRequest requestWithURL:[NSURLURLWithString:baseUrl]];
    [theRequestsetHTTPMethod:@"GET"];
    [theRequestsetValue:oauthHeader forHTTPHeaderField:@"Authorization"];
    self.connect= [[NSURLConnection alloc] initWithRequest:theRequestdelegate:self]; // 开始连接 返回值在
}

// 获取request_token之后,要做一件事情,就是让用户登录,调出新浪微博登录页面:
- (NSString*)authorizeUrl{
    //
    NSString*baseUrl = [NSString stringWithFormat:@"http://%@/oauth/authorize",SINA_T_HOST];
    NSString*url = [NSStringstringWithFormat:@"%@?oauth_token=%@&oauth_token_secret=%@&oauth_callback=%@",baseUrl, self.oauth_token, self.oauth_token_secret, @"oob"];
    returnurl;
}


///////////////
#pragma mark  webView几个delegate
- (BOOL)webView:(UIWebView *)webViewshouldStartLoadWithRequest:(NSURLRequest *)requestnavigationType:(UIWebViewNavigationType)navigationType{
    returnYES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString*pin = [self locateAuthPinInWebView:webView]; // 获取pin码
    if ([pinlength]> 0) {
      [self getAccessToken];
    }
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError*)error {
}

#pragma mark 获取oauth_verifier授权码
- (NSString *) locateAuthPinInWebView:(UIWebView*)webView  {
   NSString          *html =[webView stringByEvaluatingJavaScriptFromString:@"document.body.innerText"];
    if ([htmlhasPrefix:@"获取到的授权码:"]) {
       NSRange verifierRange=[html rangeOfString:@"获取到的授权码:"];
       NSRangeverifierRanges=NSMakeRange(verifierRange.location+verifierRange.length,6);
       NSString *verifer=[html substringWithRange:verifierRanges];
       NSLog(@"%@",verifer);
   self.oauth_verifier=verifer;
    }
    if(self.oauth_verifier.length > 0) returnself.oauth_verifier;
    if(html.length == 0) return nil;
    
    constchar         *rawHTML = (const char *) [htmlUTF8String];
   int               length = strlen(rawHTML), chunkLength = 0;
    
    for (int i =0; i < length; i++) {
      if (rawHTML[i] < '0' || rawHTML[i]> '9') {
         if (chunkLength == 6) {
            char            *buffer = (char *) malloc(chunkLength + 1);
            
            memmove(buffer, &rawHTML[i -chunkLength], chunkLength);
            buffer[chunkLength] = 0;
            
            self.oauth_verifier = [NSStringstringWithUTF8String: buffer];
            free(buffer);
            return self.oauth_verifier;
         }
         chunkLength = 0;
      } else
         chunkLength++;
    }
    returnnil;
}
#pragma mark 获取Access Token
- (void) getAccessToken {
    NSString*baseUrl = [NSStringstringWithFormat:@"http://%@/oauth/access_token",SINA_T_HOST];
    NSString*nonce = [self _generateNonce];
    NSString*timestamp = [self _generateTimestamp];
    
   NSMutableDictionary* info = [NSMutableDictionarydictionaryWithObjectsAndKeys:SINA_WEIBO_APP_KEY,@"oauth_consumer_key",
                                OAUTH_SIGNATURE_METHOD,@"oauth_signature_method",
                                timestamp,@"oauth_timestamp",
                                nonce,@"oauth_nonce",
                                self.oauth_token,@"oauth_token",
                                self.oauth_verifier,@"oauth_verifier",
                                OAUTH_VERSION,@"oauth_version",nil];
    [selfhmac_sha1_signature:@"GET" url:baseUrl param:infotoken_secret:self.oauth_token_secret];
    
    NSString*oauthHeader = [NSString stringWithFormat:@"OAuth realm="%@",oauth_consumer_key="%@", oauth_token="%@",oauth_signature_method="%@", oauth_signature="%@",oauth_timestamp="%@",oauth_verifier="%@", oauth_nonce="%@",oauth_version="1.0"",
                            @"",
                            [info valueForKey:@"oauth_consumer_key"],
                            [info valueForKey:@"oauth_token"],
                            [info valueForKey:@"oauth_signature_method"],
                            [info valueForKey:@"oauth_signature"],
                            [info valueForKey:@"oauth_timestamp"],
                            [info valueForKey:@"oauth_verifier"], //授权码
                            [info valueForKey:@"oauth_nonce"]];
    
   NSMutableURLRequest *theRequest =[NSMutableURLRequest requestWithURL:[NSURLURLWithString:baseUrl]];
    [theRequestsetHTTPMethod:@"GET"];
    [theRequestsetValue:oauthHeader forHTTPHeaderField:@"Authorization"];
    self.connect= [[NSURLConnection alloc] initWithRequest:theRequestdelegate:self];
}
----------------------NSURLConnectionDelegate-------------------
#pragma mark
#pragma mark NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)aConnectiondidReceiveResponse:(NSURLResponse *)aResponse
{
   NSHTTPURLResponse *resp = (NSHTTPURLResponse*)aResponse;
    if (resp){
      NSLog(@"Response: %d", resp.statusCode); // 返回编号
    }
}
- (void)connection:(NSURLConnection *)aConn didReceiveData:(NSData*)data
{
    NSString*stringData = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];
   NSLog(@"String Data %@",stringData); //返回信息
    //这个stringdata要截取oauth_token,oauth_token_secret
    //
}
- (void)connection:(NSURLConnection *)aConndidFailWithError:(NSError *)error
{
   [UIApplication sharedApplication].networkActivityIndicatorVisible =NO;
    
    NSString*msg = [NSString stringWithFormat:@"Error: %@ %@",[errorlocalizedDescription],[[error userInfo]objectForKey:NSErrorFailingURLStringKey]];
   NSLog(@"Connection failed: %@", msg); // 错误信息
    
}

-----------------------------------------生成签名--------------------------------
// 生成签名
-(void) hmac_sha1_signature:(NSString*) method url:(NSString*)baseUrl param:(NSDictionary*) param token_secret:(NSString*)token_secret{
    
    NSArray*sortedkeys = [[param allKeys]sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
   NSMutableString *mutUrlParam = [NSMutableStringstringWithString:@""];
    
    unsigned i,c = [sortedkeys count];
    for (i=0;i<c; i++) {
       NSString *k=[sortedkeys objectAtIndex:i];
       NSString *v=[param objectForKey:k];
       if(i>0){
           [mutUrlParam appendString:@"&"];
       }
       [mutUrlParam appendString:k];
       [mutUrlParam appendString:@"="];
       [mutUrlParam appendString:[self ab_RFC3986EncodedString:v]];// URI编码
    }
    
    NSString*urlEncodeBaseUrl = [self ab_RFC3986EncodedString:baseUrl]; // URI编码
    NSString*urlParam = (NSString*)mutUrlParam;
    urlParam =[self ab_RFC3986EncodedString:urlParam]; // URI 编码
    NSString*sbs = [NSStringstringWithFormat:@"%@&%@&%@",method, urlEncodeBaseUrl, urlParam];
    NSString*key = [NSString stringWithFormat:@"%@&%@",SECRET,token_secret];
    NSString*oauth_signature = [self hmac_sha1:key text:sbs];
    
    [paramsetValue:oauth_signature forKey:@"oauth_signature"];
    
   NSMutableString *urlParams = [NSMutableStringstringWithString:@""];
    NSArray*keys=[param allKeys];
    i, c=[keyscount];
    for (i=0;i<c; i++) {
       NSString *k=[keys objectAtIndex:i];
       NSString *v=[param objectForKey:k];
       NSString *paramStr = [NSStringstringWithFormat:@"&%@=%@",k,[selfab_RFC3986EncodedString:v]];
       [urlParams appendString:paramStr];
    }
    
    [urlParamsreplaceCharactersInRange:NSMakeRange(0,1) withString:@""];
}


- (NSString *)hmac_sha1:(NSString *)key text:(NSString*)text{
    
    const char*cKey  = [keycStringUsingEncoding:NSUTF8StringEncoding];
    const char*cData = [text cStringUsingEncoding:NSUTF8StringEncoding];
    
    charcHMAC[CC_SHA1_DIGEST_LENGTH];
    
   CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData),cHMAC);
    
    NSData *HMAC= [[NSData alloc] initWithBytes:cHMAClength:CC_SHA1_DIGEST_LENGTH];
    NSString*hash = [Base64 encode:HMAC];//base64 编码。
    [HMACrelease];
    returnhash;
}

- (NSString *)ab_RFC3986EncodedString:(NSString *)v // UTF-8encodes prior to URL encoding
{
   NSMutableString *result = [NSMutableStringstring];
    const char*p = [v UTF8String];
    unsignedchar c;
    
    for(; c =*p; p++)
    {
      switch(c)
      {
         case '0' ... '9':
         case 'A' ... 'Z':
         case 'a' ... 'z':
         case '.':
         case '-':
         case '~':
         case '_':
            [result appendFormat:@"%c", c];
            break;
         default:
            [result appendFormat:@"%%X", c];
      }
    }
    returnresult;
}



--------------------------我的问题------------------------------
#pragma mark SendWeiBo

// 这个东西呢,我一直返回的信息是错误的。有时是少个appkey。有时候是验证失败。
// 如果有高人的话,麻烦帮我解答下。
-(IBAction) send {
    NSString*message = [m_textField text]; // 获取发送的文本内容
    if ([messagelength] > 0) {
      self.oauthType = 3;
      NSString *baseUrl = [NSStringstringWithFormat:@"http://%@/statuses/update.xml",SINA_T_HOST];
      NSString *nonce = [self _generateNonce];
      NSString *timestamp = [self_generateTimestamp];
      NSString *status = message;
      NSMutableDictionary* info = [NSMutableDictionarydictionaryWithObjectsAndKeys:
                            SINA_WEIBO_APP_KEY,@"oauth_consumer_key",
                            nonce,@"oauth_nonce",
                           OAUTH_SIGNATURE_METHOD,@"oauth_signature_method",
                            timestamp,@"oauth_timestamp",
                            self.oauth_token,@"oauth_token",
                            self.oauth_verifier,@"oauth_verifier",
                            OAUTH_VERSION,@"oauth_version",
                            SINA_WEIBO_APP_KEY,@"source",
                            status,@"status",
                            nil];
      
      [self hmac_sha1_signature:@"POST" url:baseUrlparam:info token_secret:self.oauth_token_secret];
      
      NSString *oauthHeader = [NSStringstringWithFormat:@"OAuth realm="%@", oauth_consumer_key="%@",oauth_token="%@", oauth_signature_method="%@",oauth_signature="%@", oauth_timestamp="%@", oauth_nonce="%@",oauth_version="1.0", source="%@" ",
                         @"",
                         [info valueForKey:@"oauth_consumer_key"],
                         [info valueForKey:@"oauth_token"],
                         [infovalueForKey:@"oauth_signature_method"],
                         [info valueForKey:@"oauth_signature"],
                         [info valueForKey:@"oauth_timestamp"],
                         [info valueForKey:@"oauth_nonce"],
                         [info valueForKey:@"source"],
                         [info valueForKey:@"status"]
                         ];//,status="%@"

      NSMutableURLRequest *theRequest =[NSMutableURLRequest requestWithURL:[NSURLURLWithString:baseUrl]];
      [theRequest setHTTPMethod:@"POST"];
      [theRequest setHTTPShouldHandleCookies:NO];
      [theRequestsetValue:@"application/x-www-form-urlencoded"forHTTPHeaderField:@"Content-Type"];
      int contentLength = [oauthHeaderlengthOfBytesUsingEncoding:NSUTF8StringEncoding];
      [theRequest setValue:[NSStringstringWithFormat:@"%d", contentLength]forHTTPHeaderField:@"Content-Length"];
      [theRequest setHTTPBody:[oauthHeaderdataUsingEncoding:NSUTF8StringEncoding]];
      self.connect = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
    }
}