Sian 发表于 2014-4-16 00:22:27

ios实战开发之仿新浪微博(第四讲:OAuth认证)

1、效果演示

http://player.youku.com/player.php/sid/XNjk5MzY4MDAw/v.swf

2、设计思路
2.1 创建一个OAuth认证控制器,并加载一个WebView
2.2 WebView加载新浪认证的URL(注册新浪帐号并成为新浪开发者),参照 http://open.weibo.com
2.3 使用WebView的代理方法发送RequestToken获取AccessToken
2.3.1 通过返回的URL截取code值即为requestToken
2.3.2 新建一个工具类封装第三方框架(AFNetWorking)的抓取网页数据方法获取JSON
2.3.3 创建一个数据模型保存JSON并归档
2.4 通过判断归档中是否存在AccessToken来修改当前显示的View,如果没有跳转到认证界面,如果有直接跳转到MainView

3、关键代码
SAOAuthController.h
//
//SAOAuthController.h
//SianWeibo
//
//Created by yusian on 14-4-14.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface SAOAuthController : UIViewController

@end

SAOAuthController.m
//
//SAOAuthController.m
//SianWeibo
//
//Created by yusian on 14-4-14.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAOAuthController.h"
#import "SACommon.h"
#import "SAHttpTool.h"
#import "SAAccountTool.h"
#import "SAMainController.h"
#import "MBProgressHUD.h"

@interface SAOAuthController () <UIWebViewDelegate>
{
    UIWebView *_webView;
}

@end

@implementation SAOAuthController

#pragma mark 设置WebView为主View
-(void)loadView
{
    _webView = [ initWithFrame:.applicationFrame];
    self.view = _webView;
    _webView.delegate = self;
}

#pragma mark 加载web数据到View
- (void)viewDidLoad
{
    ;
    // 1 拼接请求授权的URL
    NSString *requestRULString = ;
    NSURL *url = ;
   
    // 2 将请求的页面加载到WebView
    NSURLRequest *request = [ initWithURL:url];
    ;
}

#pragma mark 代理方法获取Token
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    // 1、获取全路径,将URL转换成字符串
    NSString *url = request.URL.absoluteString;
   
    // 2、查找code范围
    NSRange range = ;       // 匹配包含"code="的URL
    if (range.length){                                  // 如果有,取"code="后跟的串,即为requestToken
      NSInteger index = range.location + range.length;
      NSString *requestToken = ;
      
    // 3、换取accessToken
      ;
      
      return NO;
    }
    return YES;
}

-(void)getAccessToken:(NSString *)requestToken
{
    // SAHttpTool类中自定义方法,实为封装AFNetWorking的方法获取网页数据
    [SAHttpTool httpToolPostWithBaseURL:@"https://api.weibo.com" path:@"oauth2/access_token" params:
   @{
       // 新浪要求必须传递的五个参数
       @"client_id" : kAppKey,
       @"client_secret" : kAppSecret,
       @"grant_type" : @"authorization_code",
       @"code" : requestToken,
       @"redirect_uri" : kRedirect_uri
      
       // 成功获取JSON
       } success:^(id JSON) {
         
         MyLog(@"请求成功");
         
         // 1 将JSON转换成数据模型并归档
         SAAccount *account = ;
         [ saveAccount:account];
         
         // 2 跳转到主页面
         self.view.window.rootViewController = [init];
         // MyLog(@"%@", JSON);
         
         // 3 清除页面加载提示
         ;
         
       // 获取信息失败
       } failure:^(NSError *error) {
         
         // 1 打印错误提示
         MyLog(@"请求失败-%@", );
         
         // 2 清除页面加载提示
         ;
       }];
}

#pragma mark - webView的两个代理方法
#pragma mark 开始加载页面时调用
- (void)webViewDidStartLoad:(UIWebView *)webView
{
    // 引入第三方框架"MBProgressHUD"添加页面加载提示
    MBProgressHUD *hud = ;
    hud.labelText = @"小龙虾加油中...";                  // 设置文字
    hud.labelFont = ;
}

#pragma mark 页面加载完毕后调用
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    // 清除页面加载提示
    ;
}

@end

SAAccount.h
//
//SAAccount.h
//SianWeibo
//
//Created by yusian on 14-4-15.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface SAAccount : NSObject <NSCoding>

@property (nonatomic, copy) NSString    *accessToken;
@property (nonatomic, copy) NSString    *expiresIn;
@property (nonatomic, copy) NSString    *remindIn;
@property (nonatomic, copy) NSString    *uid;

- (id)initWithDict:(NSDictionary *)dict;

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

@end

SAAccount.m
//
//SAAccount.m
//SianWeibo
//
//Created by yusian on 14-4-15.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAAccount.h"

@implementation SAAccount

- (id)initWithDict:(NSDictionary *)dict
{
    if (self = )
    {
      self.accessToken = dict[@"access_token"];
      self.expiresIn = dict[@"expires_in"];
      self.remindIn = dict[@"remind_in"];
      self.uid = dict[@"uid"];
    }
    return self;
}

+ (id)accountWithDict:(NSDictionary *)dict
{
    return [ initWithDict:dict];
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    ;
    ;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = ) {
      self.accessToken = ;
      self.uid = ;
    }
    return self;
}

@end

SAAccountTool.h
//
//SAAccountTool.h
//SianWeibo
//
//Created by yusian on 14-4-15.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

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

@interface SAAccountTool : NSObject

@property (nonatomic, readonly) SAAccount *account;

+ (SAAccountTool *)sharedAccountTool;

- (void)saveAccount:(SAAccount *)account;

@end

SAAccountTool.m
//
//SAAccountTool.m
//SianWeibo
//
//Created by yusian on 14-4-15.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAAccountTool.h"
#define kAccountFile stringByAppendingString:@"/account.data"]

@implementation SAAccountTool

// 单例创建三个条件
// 1、全局实例
static SAAccountTool *_instance;

// 2、类创建方法
+ (SAAccountTool *)sharedAccountTool
{
    if (_instance) {
      _instance = [ init];
    }
    return[ init];
}

// 3、重写alloc方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
      _instance = ;
    });
    return _instance;
}

// 单例在MRC中还需要重写以下三个方法
/******************************
-(oneway void)release
{
    return;
}
-(id)retain
{
    return self;
}
-(NSUInteger)retainCount
{
    return 1;
}
*******************************/

- (id)init
{
    if (self = ) {
      _account = ;
    }
    return self;
}

- (void)saveAccount:(SAAccount *)account
{
    _account = account;
    ;
}

@end

SAHttpTool.h
//
//SAHttpTool.h
//SianWeibo
//
//Created by yusian on 14-4-15.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef void (^Success)(id JSON);
typedef void (^Failure)(NSError *error);

@interface SAHttpTool : NSObject

+ (void)httpToolPostWithBaseURL:(NSString *)urlString path:(NSString *)pathString params:(NSDictionary *)params success:(Success)success failure:(Failure)failure;

@end

SAHttpTool.m
//
//SAHttpTool.m
//SianWeibo
//
//Created by yusian on 14-4-15.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAHttpTool.h"
#import "AFNetWorking.h"

@implementation SAHttpTool

// 包装第三方框架AFNetWorking,对外提供类似方法
+ (void)httpToolPostWithBaseURL:(NSString *)urlString path:(NSString *)pathString params:(NSDictionary *)params success:(Success)success failure:(Failure)failure
{
    // 获取授权
    // 1、创建一个Operation
    AFHTTPClient *client = [ initWithBaseURL:];
    NSURLRequest *post = ;
   
    // 2、发送Operation请求
    AFJSONRequestOperation *json = [AFJSONRequestOperation JSONRequestOperationWithRequest:post
                                    
      success:
      ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
            
            success(JSON);      // 将方法中的实参传给内部的Success Block调用
      }
                                    
      failure:
      ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
            
            failure(error);   // 将方法中的error传给内部的Failure Block调用
      }];
   
    ;
}

@end


4、源码下载
**** Hidden Message *****

相关主题链接
1、ios实战开发之仿新浪微博(第一讲:新特性展示)
2、ios实战开发之仿新浪微博(第二讲:主框架搭建)
3、ios实战开发之仿新浪微博(第三讲:更多界面搭建)
4、ios实战开发之仿新浪微博(第四讲:OAuth认证)
5、ios实战开发之仿新浪微博(第五讲:微博数据加载)
6、ios实战开发之仿新浪微博(第六讲:微博数据展示一)
7、ios实战开发之仿新浪微博(第七讲:微博数据展示二)
8、ios实战开发之仿新浪微博(第八讲:微博数据展示三)
9、ios实战开发之仿新浪微博(第九讲:微博功能完善一)
10、ios实战开发之仿新浪微博(第十讲:微博功能完善二)
11、ios实战开发之仿新浪微博(第十一讲:微博功能完善三)
12、ios实战开发之仿新浪微博(小龙虾发布版)

Miul 发表于 2015-7-5 13:15:12

给使用AFNetworking2.0以上版本的同学提个醒,新浪返回access_Token数据时,有个坑。
AFJSONRequestOperation默认不接收text/plain类型的数据,当服务器返回text/plain类型的数据时,会认为出错了。可以通过修改源代码解决问题

+ (NSSet *)acceptableContentTypes {

    return ;

}

panzilong 发表于 2014-10-24 13:46:43

继续感谢!!!!!

qiulibi 发表于 2014-11-5 22:12:14

看着挺好的,收藏了

yipangzi 发表于 2014-11-20 10:28:16

囫囵吞枣啊、、、、、、、

ztt0422jiayou 发表于 2014-11-23 17:03:53

挺好的,学习了

warmlight 发表于 2014-11-26 10:11:48

继续学习怎么进行OAuth认证

Zhangyuge 发表于 2014-12-18 17:10:27

支持个,学习学习

hnxyzhw 发表于 2014-12-20 19:59:34

继续学习怎么进行OAuth认证

lihaitao 发表于 2014-12-22 15:52:24

请问kOAuthURL、kAppKey、kRedirect_url这三个常量在哪?

Sian 发表于 2014-12-23 08:58:22

lihaitao 发表于 2014-12-22 15:52
请问kOAuthURL、kAppKey、kRedirect_url这三个常量在哪?

Classes--Other--SACommon.h 工程常量文件
页: [1] 2 3 4 5 6
查看完整版本: ios实战开发之仿新浪微博(第四讲:OAuth认证)