iOS 新浪微博-4.0 OAuth授权

申请开发者

想要拉到到新浪微博的数据,首先让自己成为开发者。申请成为开发者账号很简单,只要有新浪微博的账号即可。

申请地址:http://open.weibo.com/

在开发的过程中,我们需要拿到几下几个值:

AppKey :分配给每个第三方应用的 app key。用于鉴权身份,显示来源等功能。

AppSecret :分配给每个第三方应用的 app 私钥。

RedirectURI:应用回调页面,可在新浪微博开放平台->我的应用->应用信息->高级应用->授权设置->应用回调页中找到。

为了方便测试,除了可以使用当前开发者账户外,还可以自己添加15个关联测试账号。

开发实现

授权相关文档:http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6

实现思路:

  1. 拼接参数,请求OAuth2/authorize ,拿到授权Code值。
  2. 通过授权code值及相关申请的参数,拿到用户授权UID及过期时间
  3. 将返回的用户信息存入沙盒里
  4. 下次打开应用时,先从沙盒里获取,获取为nil时再请求网络

导入相关第三方库

直接在cocoapods里导入以下的类库

  • 网络请求:AFNetworking
  • 吐丝:MBProgressHUD
platform :ios,‘7.0‘
pod "AFNetworking","2.5.4"
pod ‘MBProgressHUD‘, ‘~> 0.9.1‘

由于在很多地方都会使用到AFNetworking,为了不让该第三方库类“污染”,特意给AFNetworking封装一层,方便以后切换第三方网络请求类,同时也方便引用管理。

HttpTool.h

#import <Foundation/Foundation.h>

@interface HttpTool : NSObject

+ (void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id json))success failure:(void (^)(NSError *error))failure;
+ (void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id json))success failure:(void (^)(NSError *error))failure;

@end

HttpTool.m

#import "HttpTool.h"
#import "AFNetworking.h"

@implementation HttpTool

+ (void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id json))success failure:(void (^)(NSError *error))failure
{
    // 1.创建请求管理者
    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];

    mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/javascript",@"text/plain", nil];

    // 2.发送请求
    [mgr GET:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (success) {
            success(responseObject);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if (failure) {
            failure(error);
        }
    }];
}

+ (void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id json))success failure:(void (^)(NSError *error))failure
{
    // 1.创建请求管理者
    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];

    mgr.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/javascript",@"text/plain", nil];

    // 2.发送请求
    [mgr POST:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (success) {
            success(responseObject);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if (failure) {
            failure(error);
        }
    }];
}

@end

定义账户常量

申请下来的账号信息,我们使用常用来存储,当然,一些常用的不变的通用字符串,我们也统一放在常量里,需要避免使用宏。可以参考:http://www.jianshu.com/p/f83335e036b5

Const.h

#import <Foundation/Foundation.h>

extern NSString * const AppKey;
extern NSString * const RedirectURI;
extern NSString * const AppSecret;

Const.m

#import "Const.h"

// 账号信息
NSString * const AppKey = @"762197719";
NSString * const RedirectURI = @"http://www.baidu.com";
NSString * const AppSecret = @"89d739c387e3a69aaad0270da66c02ff";

归档access_token工具类

由于access_token不经常变,我们需要将拿到的access_token归档存起来,每次登录的时候,先判断access_token是否有效(存在且不过期)。

归档使用模型,需要实现NSCoding协议,定义模型

Account.h

#import <Foundation/Foundation.h>

@interface Account : NSObject<NSCoding>

/** string    用于调用access_token,接口获取授权后的access token。*/
@property (nonatomic, copy) NSString *access_token;

/** string    access_token的生命周期,单位是秒数。*/
@property (nonatomic, copy) NSNumber *expires_in;

/** string    当前授权用户的UID。*/
@property (nonatomic, copy) NSString *uid;

/**    access token的创建时间 */
@property (nonatomic, strong) NSDate *created_time;

/** 用户的昵称 */
@property (nonatomic, copy) NSString *name;

+ (instancetype)accountWithDict:(NSDictionary *)dict;

@end

Account.m

#import "Account.h"

@implementation Account

+(instancetype)accountWithDict:(NSDictionary *)dict
{
    Account *account = [[self alloc] init];
    account.access_token = dict[@"access_token"];
    account.uid = dict[@"uid"];
    account.expires_in = dict[@"expires_in"];
    // 获得账号存储的时间(accessToken的产生时间)
    account.created_time = [NSDate date];
    return account;
}

/**
 *  当一个对象要归档进沙盒中时,就会调用这个方法
 *  目的:在这个方法中说明这个对象的哪些属性要存进沙盒
 */
- (void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.access_token forKey:@"access_token"];
    [encoder encodeObject:self.expires_in forKey:@"expires_in"];
    [encoder encodeObject:self.uid forKey:@"uid"];
    [encoder encodeObject:self.created_time forKey:@"created_time"];
    [encoder encodeObject:self.name forKey:@"name"];
}

/**
 *  当从沙盒中解档一个对象时(从沙盒中加载一个对象时),就会调用这个方法
 *  目的:在这个方法中说明沙盒中的属性该怎么解析(需要取出哪些属性)
 */
- (id)initWithCoder:(NSCoder *)decoder
{
    if (self = [super init]) {
        self.access_token = [decoder decodeObjectForKey:@"access_token"];
        self.expires_in = [decoder decodeObjectForKey:@"expires_in"];
        self.uid = [decoder decodeObjectForKey:@"uid"];
        self.created_time = [decoder decodeObjectForKey:@"created_time"];
        self.name = [decoder decodeObjectForKey:@"name"];
    }
    return self;
}

@end

为了方便直接归档和从归档里读取模型,定义一个AccountTool工具类

AccountTool.h

#import <Foundation/Foundation.h>
#import "Account.h"

@interface AccountTool : NSObject

/**
 *  存储账号信息
 *
 *  @param account 账号模型
 */
+ (void)saveAccount:(Account *)account;

/**
 *  返回账号信息
 *
 *  @return 账号模型(如果账号过期,返回nil)
 */
+ (Account *)getAccount;

@end

AccountTool.m

//
//  AccountTool.m
//  Weibo
//
//  Created by jiangys on 15/10/17.
//  Copyright © 2015年 Jiangys. All rights reserved.
//

#import "AccountTool.h"
#import "Account.h"

// 账号的存储路径
#define AccountPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"account.archive"]

@implementation AccountTool

/**
 *  存储账号信息
 *
 *  @param account 账号模型
 */
+ (void)saveAccount:(Account *)account
{
    // 自定义对象的存储必须用NSKeyedArchiver,不再有什么writeToFile方法
    [NSKeyedArchiver archiveRootObject:account toFile:AccountPath];
}

/**
 *  返回账号信息
 *
 *  @return 账号模型(如果账号过期,返回nil)
 */
+ (Account *)getAccount
{
    // 加载模型
    Account *account = [NSKeyedUnarchiver unarchiveObjectWithFile:AccountPath];

    /* 验证账号是否过期 */

    // 过期的秒数
    long long expires_in = [account.expires_in longLongValue];
    // 获得过期时间
    NSDate *expiresTime = [account.created_time dateByAddingTimeInterval:expires_in];
    // 获得当前时间
    NSDate *now = [NSDate date];

    // 如果expiresTime <= now,过期
    /**
     NSOrderedAscending = -1L, 升序,右边 > 左边
     NSOrderedSame, 一样
     NSOrderedDescending 降序,右边 < 左边
     */
    NSComparisonResult result = [expiresTime compare:now];
    if (result != NSOrderedDescending) { // 过期
        return nil;
    }

    return account;
}

@end

获取并存储access_token

控制器需要调用authorize获得的code值,再通过code值获取access_token

OAuthViewController.h

#import <UIKit/UIKit.h>

@interface OAuthViewController : UIViewController

@end

OAuthViewController.m

//
//  OAuthViewController.m
//  Weibo
//
//  Created by jiangys on 15/10/17.
//  Copyright © 2015年 Jiangys. All rights reserved.
//

#import "OAuthViewController.h"
#import "Const.h"
#import "HttpTool.h"
#import "MBProgressHUD+YS.h"
#import "Account.h"
#import "AccountTool.h"

@interface OAuthViewController() <UIWebViewDelegate>

@end

@implementation OAuthViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 1.创建一个webView
    UIWebView *webView=[[UIWebView alloc] init];
    webView.frame=self.view.bounds;
    webView.delegate=self;
    [self.view addSubview:webView];

    // 2.用webView加载新浪登录页面
    NSString *urlStr=[NSString stringWithFormat:@"https://api.weibo.com/oauth2/authorize?client_id=%@&redirect_uri=%@",AppKey,RedirectURI];
    NSURLRequest *requestUrl=[NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
    [webView loadRequest:requestUrl];
}

#pragma mark - webView代理方法
-(void)webViewDidStartLoad:(UIWebView *)webView
{
    [MBProgressHUD showMessage:@"正在加载..."];
}

-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    [MBProgressHUD hideHUD];
}

-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    [MBProgressHUD hideHUD];
}

/**
 *  监听所有跳转方法
 */
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *url=request.URL.absoluteString;
    NSRange range=[url rangeOfString:@"code="];
    if (range.length != 0) {
        // 截取code=后面的参数值
        NSUInteger fromIndex=NSMaxRange(range);
        NSString *code=[url substringFromIndex:fromIndex];

        // 利用code换取一个accessToken
        [self accessTokenWithCode:code];

        // 禁止加载回调地址
        return NO;
    }

    return true;
}

/**
 *  获取token
 *
 *  @param code 授权码
 */
- (void)accessTokenWithCode:(NSString *)code
{
    NSMutableDictionary *params=[NSMutableDictionary dictionary];
    params[@"client_id"] = AppKey;
    params[@"client_secret"] = AppSecret;
    params[@"grant_type"] = @"authorization_code";
    params[@"redirect_uri"] = RedirectURI;
    params[@"code"] = code;

    [HttpTool post:@"https://api.weibo.com/oauth2/access_token" params:params success:^(id json)
     {
         [MBProgressHUD hideHUD];

         // 将返回的账号字典数据 --> 模型,存进沙盒
         Account *account = [Account accountWithDict:json];

         // 存储账号信息
         [AccountTool saveAccount:account];

         // 切换窗口的根控制器
         UIWindow *window = [UIApplication sharedApplication].keyWindow;
         [window switchRootViewController];

     }failure:^(NSError *error) {
         [MBProgressHUD hideHUD];
         YSLog(@"--MBProgressHUD_error--%@",error);
     }];
}

@end

登录验证access_token

每次登录的时候,都需要判断access_token是否有效(存在且不过期)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window=[[UIWindow alloc]init];
    self.window.frame=[UIScreen mainScreen].bounds;

    // 2.设置根控制器
    Account *account = [AccountTool getAccount];
    if (account) { // 之前已经登录成功过
        [self.window switchRootViewController];
    } else {
        self.window.rootViewController = [[OAuthViewController alloc] init];
    }

    [self.window makeKeyAndVisible];

    return YES;
}

章节源代码下载:http://pan.baidu.com/s/1sjmoEw1

新浪微博Github:https://github.com/jiangys/Weibo

时间: 2024-10-05 07:34:09

iOS 新浪微博-4.0 OAuth授权的相关文章

[iOS微博项目 - 2.0] - OAuth授权3步

A.概念 OAUTH协议为用户资源的授权提供了一个安全的.开放而又简易的标准.与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的.oAuth是Open Authorization的简写. B.使用3步骤 OAUTH认证授权就三个步骤,三句话可以概括: 1. 获取未授权的Request Token 2. 获取用户授权的Request Token 3. 用授权的Requ

【IOS】App中OAuth授权的实现方式

OAuth 授权在 iOS 中的实现方式 在 iOS App 中,需要绑定微博.twitter.flickr 等第三方平台账号时,一般用OAuth 授权的方式. OAuth 1.0 授权大致分为以下三步: 客户端向平台申请一个 request token,该 token 是未授权的: 客户端打开平台提供的登陆页面,引导用户输入用户名密码,对 request token 进行授权. 登陆页面的 url 中会附带一个 redirect_url,当授权成功后会重定向到这个地址,返回客户端. 客户端拿着

iOS 新浪微博-5.0 首页微博列表

首页显示微博列表,是微博的核心部分,这一章节,我们主要是显示出微博的列表. 导入第三方类库 pod 'SDWebImage', '~> 3.7.3' pod 'MJRefresh', '~> 2.4.12' pod 'MJExtension', '~> 2.5.14' 需求分析 由于Cell的高度是不一样的,因而采用自定义cell的方式来实现.具体实现思路,请参数之前的文章: iOS UI基础-9.2 UITableView 简单微博列表 代码实现 1.根据新浪微博的API文档,需要定义

iOS新浪微博OAuth2.0认证代码

#import "ViewController.h" #import "AFNetworking.h" @interface ViewController ()<UIWebViewDelegate> @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //1.使用webview UIWebView *webView = [[UIWebView all

ios 新浪微博Oauth授权失败 (error:redirect_rul_mismatch)

原因:移动端应用Oauth授权,不需要填写回调地址,不像web端,把下面的地址删除即可 ps:实际上他是有回调的,地址为:http:// ios 新浪微博Oauth授权失败 (error:redirect_rul_mismatch),布布扣,bubuko.com

iOS5.0以上使用新浪微博开放平台OAuth 续(及解决登录无效问题)

新浪微博开放平台为第三方应用提供了简便的合作模式,满足了手机用户和平板电脑用户随时随地分享信息的需求.通过调用平台的api即可实现很多微博上的功能. 本篇主要目的是记录新浪微博移动SDK iOS版本的在iOS5下的嵌入和使用. 1.申请一个新浪微博的移动应用 . 申请地址:http://open.weibo.com/development,申请后得到App key 和 App Secret 2.下载iOS_sdk 下载地址:http://open.weibo.com/wiki/SDK#iOS_S

IOS OAuth授权分析

一.黑马微博 ---> 用户的微博数据1.成为新浪的开发者(加入新浪微博的开发阵营)* 注册一个微博帐号,登录http://open.weibo.com帐号:[email protected]密码:ios4762450* 填写开发者的个人信息(比如姓名.出生日期.上传身份证) 2.创建应用* 假设应用名称叫做"黑马微博"* 应用创建完毕,默认就进入"开发"阶段,就具备了授权的资格* 应用相关数据App Key:3141202626 // 应用的唯一标识App

OAuth授权详解,以新浪微博为例

/* //OAuth授权过程: 1.登陆账号 http://open.weibo.com 注册一下开发者信息,成为新浪的开发者 2.点击"移动应用",创建一个应用(勾选应用名称,应用平台就可以了),页面跳转,显示到"开发阶段即可" 3.回到主页面,点击API接口>首页>OAuth2.0授权认证 根据说明点击进入(1)OAuth2/authorize     获取code(使用get请求) 点击进入(2)OAuth2/access_token     获取

iOS开发 - 第05篇 - 项目 - 03 - 版本新特性 &amp; OAuth授权

1.版本新特性 1.1 界面 程序第一次启动的时候会弹出新特性界面,之后启动不会出现. 1.2 实现思路 1> 新建一个HWNewfeatureViewController(继承自UIViewController) 2> 先将其设置为整个程序的根控制器,用于演示 3> 使用UIScrollView 4>添加UIPageControl 5> 设置UIScrollView代理,监听滚动,设置UIPageControl 2.控制器切换 2.1 一个View中显示其他控制器的View