IOS OAuth授权分析

一、黑马微博 ---> 用户的微博数据
1.成为新浪的开发者(加入新浪微博的开发阵营)
* 注册一个微博帐号,登录http://open.weibo.com
帐号:643055866@qq.com
密码:ios4762450
* 填写开发者的个人信息(比如姓名、出生日期、上传身份证)

2.创建应用
* 假设应用名称叫做“黑马微博”
* 应用创建完毕,默认就进入“开发”阶段,就具备了授权的资格
* 应用相关数据
App Key:3141202626 // 应用的唯一标识
App Secret:ee9de4d2431be061b22fe328332a5228
Redirect URI:http://www.itheima.com

3.用户对“黑马微博”进行资源授权----OAuth授权2.0
1> 获取未授权的Request Token : 展示服务器提供商提供的登录页面
* URL : https://api.weibo.com/oauth2/authorize
* 参数
client_id     true     string     申请应用时分配的AppKey // 得知道给哪个应用授权
redirect_uri     true     string     授权回调地址 // 授权成功后跳转到哪个页面

2> 获取授权过的Request Token
* 授权成功后,自动跳转到回调页面,比如
http://www.itheima.com/?code=eabdc03cc4cc51484111b1cfd9c4cd0b
// 新浪会在回调页面后面拼接一个参数:授权成功后的Request Token

3> 根据授权过的Request Token换取一个Access Token
* URL : https://api.weibo.com/oauth2/access_token
* 参数
client_id     true     string     申请应用时分配的AppKey。
client_secret     true     string     申请应用时分配的AppSecret。
grant_type     true     string     请求的类型,填写authorization_code
code     true     string     调用authorize获得的code值。
redirect_uri     true     string     回调地址,需需与注册应用里的回调地址一致
* 返回结果
{
    "access_token" = "2.00vWf4GEUSKa7D739148f7608SXA9B";
    "expires_in" = 157679999;
    "remind_in" = 157679999;
    uid = 3758830533;
}
// uid == user_id == 当前登录用户的ID   == 用户的唯一标识

{
    "access_token" = "2.00vWf4GEUSKa7D739148f7608SXA9B";
    "expires_in" = 157679999;
    "remind_in" = 157679999;
    uid = 3758830533;
}

* access_token和uid的去呗
access_token : 1个用户给1个应用授权成功后,就获得对应的1个access_token,作用是:允许1个应用访问1个用户的数据
uid:1个用户对应1个uid,每1个用户都有自己唯一的uid
举例:
张三
李四

应用1
应用2

张三给应用1、应用2授权成功了:1个uid、2个access_token
李四给应用2授权成功了:1个uid、1个access_token
上面操作:产生了2个uid,3个access_token

二、授权过程中常见错误:
1.invalid_request
1> 没有传递必填的请求参数
2> 请求参数不对
3> URL中间留有空格

2.invalid_client
1> client_id的值传递错误(AppKey不对)

3.redirect_uri_mismatch
1> 回调地址不对

三、授权帐号注意
1.如果应用还没有经过新浪审核,只能访问自己或者其他15个测试帐号的微博数据

 

授权code (HMOAuthViewController.m)

#import "HMOAuthViewController.h"
#import "MBProgressHUD+MJ.h"
#import "AFNetworking.h"
#import "HMTabBarViewController.h"
#import "HMNewfeatureViewController.h"

@interface HMOAuthViewController () <UIWebViewDelegate>

@end

@implementation HMOAuthViewController
- (void)viewDidLoad
{
    [super viewDidLoad];

    //1.创建UIWebView
    UIWebView * webView=[[UIWebView alloc]init];
    webView.frame=self.view.frame;
    [self.view addSubview:webView];
    
    //2.加载登录页面
    NSURL *url=[NSURL URLWithString:@"https://api.weibo.com/oauth2/authorize?client_id=881257207&redirect_uri=http://blog.sina.com.cn"];
    
    NSURLRequest *request=[NSURLRequest requestWithURL:url];
    [webView loadRequest:request];
    
    //3.设置代理
    webView.delegate=self;
}

#pragma mark - UIWebViewDelegate
/**
 *UIWebView开始加载资源的时候调用(开始发送请求)
 *
 */
-(void)webViewDidStartLoad:(UIWebView *)webView
{
    [MBProgressHUD showMessage:@"正在加载中......"];
}
/**
 *UIWebView加载完毕的时候调用(请求完毕)
 *
 */
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    [MBProgressHUD hideHUD];
}
/**
 *UIWebView加载失败的时候调用(请求失败)
 *
 */
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    [MBProgressHUD hideHUD];
}

/**
 *UIWebView每当发送一个请求之前,都会先调用这个代理方法(询问代理允不允许加载这个请求)
 *
 *@param request     即将发送的请求
 *@reture Yes    允许加载   NO:禁止加载
 */
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    //1.获得请求地址
    NSString  *url=request.URL.absoluteString;
    
    //2.判断url是否为回调地址
    /** ~~~~
     url = http://www.itheima.com/?code=a3db74011c311e629bafce3e50c25339
     range.location == 0
     range.length > 0
     */
    /**
     url =  https://api.weibo.com/oauth2/authorize
     range.location == NSNotFound
     range.length == 0
     */
    NSRange range=[url rangeOfString:@"http://blog.sina.com.cn/?code="];
    if(range.location!=NSNotFound)//是回调地址
    {
    //截取授权成功后的请求标记
        int from=range.location+range.length;
        NSString *code=[url substringFromIndex:from];
        
        //根据code获得一个accessToken
        [self accessTokenWithCode:code];
        
        //禁止加载回调页面
        return  NO;
    }
    
    
    return YES;

}
/**
 *根据code获得一个accessToken
 *
 *@param code 授权成功后的请求标记
 */
-(void)accessTokenWithCode:(NSString *)code
{

    //1.获得请求管理者
    AFHTTPRequestOperationManager *mgr=[AFHTTPRequestOperationManager manager];
    
    //2.封装请求参数
    NSMutableDictionary *params=[NSMutableDictionary dictionary];
    params[@"client_id"]=@"881257207";
    params[@"client_secret"]=@"0b8c34d4659d656834f827abfb3a1805";
    params[@"redirect_uri"]=@"http://blog.sina.com.cn";
    params[@"grant_type"]=@"authorization_code";
    params[@"code"]=code;
    
    //3.发送POST请求
    [mgr POST:@"https://api.weibo.com/oauth2/access_token" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
        
        //隐藏HUD
        [MBProgressHUD hideHUD];
        HMLog(@"请求成功。。。。。");
        
        //存储授权成功的帐号信息
        NSString *doc=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
        NSString *filepth=[doc stringByAppendingPathComponent:@"account.plist"];
        [responseObject writeToFile:filepth atomically:YES];
        
        //切换控制器(可能去新特性	abBar)
        //如何知道第一次使用这个版本?比较上次的使用情况
        NSString * versionKey=(__bridge NSString*)kCFBundleVersionKey;
        
        //从沙盒中取出上次存储的软件版本号(取出用户上次的使用记录)
        NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
        NSString *lastVersion=[defaults objectForKey:versionKey];
        
        //获得当前打开软件的版本号
        NSString *currentVersion=[NSBundle mainBundle].infoDictionary[versionKey];
        
        
        UIWindow *window=[UIApplication sharedApplication].keyWindow;
        if([currentVersion isEqualToString:lastVersion])//当前版本号==上次使用的版本:显示HMTabBarViewController
        {
            window.rootViewController=[[HMTabBarViewController alloc]init];
        }
        else{//当前版本号 !=上次使用的版本:显示版本新特性
            window.rootViewController=[[HMNewfeatureViewController alloc]init];
            
            //存储这次使用的软件版本
            [defaults setObject:currentVersion forKey:versionKey];
            [defaults synchronize];
        }
        
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //隐藏HUD
        [MBProgressHUD hideHUD];
        HMLog(@"请求失败--@",error);
    }];
}
/**
 Request failed: unacceptable content-type: text/plain
 */
@end
View Code

 调用code 信息

#import "AppDelegate.h"
#import "HMTabBarViewController.h"
#import "HMNewfeatureViewController.h"
#import "HMOAuthViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


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

    
    application.statusBarHidden=NO;
    
    //1.创建窗口
    self.window=[[UIWindow alloc]init];
    self.window.frame=[UIScreen mainScreen].bounds;
    
    
    //2.设置窗口的根控制器
    NSString *doc=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
    NSString *filepath=[doc stringByAppendingPathComponent:@"account.plist"];
    NSDictionary *account=[NSDictionary dictionaryWithContentsOfFile:filepath];
    if(account){
        //如果知道第一次使用这个版本?比较上次的使用情况
        NSString *versionKey=(__bridge NSString *)kCFBundleVersionKey;
        
        //从沙盒中取出上次存储的软件版本号(取出用户上次的使用记录)
        NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
        NSString  *lastVersion=[defaults objectForKey:versionKey];
        
        //获得当前打开软件的版本号
        NSString *currentVersion=[NSBundle mainBundle].infoDictionary[versionKey];
        
        if([currentVersion isEqualToString:lastVersion])// 当前版本号 == 上次使用的版本:显示HMTabBarViewController
        {
            self.window.rootViewController=[[HMTabBarViewController alloc]init];
        } else// 当前版本号 != 上次使用的版本:显示版本新特性
        {
            self.window.rootViewController= [[HMNewfeatureViewController alloc] init];
            
            //存储这次使用的软件版本
            [defaults setObject:currentVersion forKey:versionKey];
            [defaults synchronize];
        }
        
    }else{//没有登录过
        self.window.rootViewController=[[HMOAuthViewController alloc]init];
    }
    
    
    
    //3.显示窗口(成为主窗口)
    [self.window makeKeyAndVisible];
    
    return YES;
}
原文地址:https://www.cnblogs.com/liuwj/p/6658618.html