关于Sina WeiBo API OAuth 验证(ios)

本文介绍如何在iOS应用中实现Sina Weibo API的OAuth验证过程,涉及API调用、Token获取以及使用CommonCrypto库进行签名计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

#define SINA_T_HOST 

                  @"api.t.sina.com.cn"//api.t.sina.com.cn
#define SINA_WEIBO_APP_KEY            @"YOUR APP KEY"
#define SECRET                        @"YOUR APP SECRET"
#define OAUTH_VERSION                 @"1.0"
#define OAUTH_SIGNATURE_METHOD        @"HMAC-SHA1"

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

#pragma mark 获得随时字符串 // 这个可以获取随机数,不一定要用uuid的
- (NSString *)_generateNonce
{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    NSMakeCollectable(theUUID);
    return (NSString *)string;
}
#pragma mark 获取request_token的参数
-(void) getRequestToken {
    NSString *baseUrl = [NSString stringWithFormat:@"http://%@/oauth/request_token", SINA_T_HOST];
    NSString *nonce = [self _generateNonce];
    NSString *timestamp = [self _generateTimestamp];
    
    NSMutableDictionary* info = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                 SINA_WEIBO_APP_KEY,@"oauth_consumer_key",
                                 OAUTH_SIGNATURE_METHOD,@"oauth_signature_method",
                                 timestamp,@"oauth_timestamp",
                                 nonce,@"oauth_nonce",
                                 OAUTH_VERSION,@"oauth_version",nil];
    
    [self hmac_sha1_signature:@"GET" url:baseUrl param:info token_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:[NSURL URLWithString:baseUrl]];
    [theRequest setHTTPMethod:@"GET"];
    [theRequest setValue:oauthHeader forHTTPHeaderField:@"Authorization"];
    self.connect = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; // 开始连接 返回值在
}

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


///
#pragma mark  webView几个delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    return YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString *pin = [self locateAuthPinInWebView:webView]; // 获取pin码
    if ([pin length]> 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 ([html hasPrefix:@"获取到的授权码:"]) {
        NSRange verifierRange=[html rangeOfString:@"获取到的授权码:"];
        NSRange verifierRanges=NSMakeRange(verifierRange.location+verifierRange.length, 6);
        NSString *verifer=[html substringWithRange:verifierRanges];
        NSLog(@"%@",verifer);
    self.oauth_verifier=verifer;
    }
    if (self.oauth_verifier.length > 0) return self.oauth_verifier;
    if (html.length == 0) return nil;
    
    const char            *rawHTML = (const char *) [html UTF8String];
    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 = [NSString stringWithUTF8String: buffer];
                free(buffer);
                return self.oauth_verifier;
            }
            chunkLength = 0;
        } else
            chunkLength++;
    }
    return nil;
}
#pragma mark 获取Access Token
- (void) getAccessToken {
    NSString *baseUrl = [NSString stringWithFormat:@"http://%@/oauth/access_token", SINA_T_HOST];
    NSString *nonce = [self _generateNonce];
    NSString *timestamp = [self _generateTimestamp];
    
    NSMutableDictionary* info = [NSMutableDictionary dictionaryWithObjectsAndKeys: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];
    [self hmac_sha1_signature:@"GET" url:baseUrl param:info token_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:[NSURL URLWithString:baseUrl]];
    [theRequest setHTTPMethod:@"GET"];
    [theRequest setValue:oauthHeader forHTTPHeaderField:@"Authorization"];
    self.connect = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}
----------------------NSURLConnectionDelegate-------------------
#pragma mark
#pragma mark NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(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 *)aConn didFailWithError:(NSError *)error
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    
    NSString* msg = [NSString stringWithFormat:@"Error: %@ %@",[error localizedDescription],[[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 = [NSMutableString stringWithString:@""];
    
    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 = [NSString stringWithFormat:@"%@&%@&%@", method, urlEncodeBaseUrl, urlParam];
    NSString *key = [NSString stringWithFormat:@"%@&%@",SECRET, token_secret];
    NSString *oauth_signature = [self hmac_sha1:key text:sbs];
    
    [param setValue:oauth_signature forKey:@"oauth_signature"];
    
    NSMutableString *urlParams = [NSMutableString stringWithString:@""];
    NSArray *keys=[param allKeys];
    i, c=[keys count];
    for (i=0; i<c; i++) {
        NSString *k=[keys objectAtIndex:i];
        NSString *v=[param objectForKey:k];
        NSString *paramStr = [NSString stringWithFormat:@"&%@=%@",k,[self ab_RFC3986EncodedString:v]];
        [urlParams appendString:paramStr];
    }
    
    [urlParams replaceCharactersInRange:NSMakeRange(0,1) withString:@""];
}


- (NSString *)hmac_sha1:(NSString *)key text:(NSString *)text{
    
    const char *cKey  = [key cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cData = [text cStringUsingEncoding:NSUTF8StringEncoding];
    
    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 编码。
    [HMAC release];
    return hash;
}

- (NSString *)ab_RFC3986EncodedString:(NSString *)v // UTF-8 encodes prior to URL encoding
{
    NSMutableString *result = [NSMutableString string];
    const char *p = [v UTF8String];
    unsigned char 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];
        }
    }
    return result;
}



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

// 这个东西呢,我一直返回的信息是错误的。有时是少个appkey。有时候是验证失败。
// 如果有高人的话,麻烦帮我解答下。
-(IBAction) send {
    NSString *message = [m_textField text]; // 获取发送的文本内容
    if ([message length] > 0) {
        self.oauthType = 3;
        NSString *baseUrl = [NSString stringWithFormat:@"http://%@/statuses/update.xml", SINA_T_HOST];
        NSString *nonce = [self _generateNonce];
        NSString *timestamp = [self _generateTimestamp];
        NSString *status = message;
        NSMutableDictionary* info = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                     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:baseUrl param:info token_secret:self.oauth_token_secret];
        
        NSString *oauthHeader = [NSString stringWithFormat:@"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"],
                                 [info valueForKey:@"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:[NSURL URLWithString:baseUrl]];
        [theRequest setHTTPMethod:@"POST"];
        [theRequest setHTTPShouldHandleCookies:NO];
        [theRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        int contentLength = [oauthHeader lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
        [theRequest setValue:[NSString stringWithFormat:@"%d", contentLength] forHTTPHeaderField:@"Content-Length"];
        [theRequest setHTTPBody:[oauthHeader dataUsingEncoding:NSUTF8StringEncoding]];
        self.connect = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值