最近无聊找一些开放平台提供的资源,做一些第三方应用练练手。
对于微博类开放平台,因为很早前还在做Android的时候做过一次,没什么新鲜感。
恰巧本人以前玩豆瓣,对于豆瓣社区的一些资源还是比较感兴趣,比如小组,评论,书电影音乐资源。
虽然最后浏览完API后,发现已开发的几个接口,相对来说做一个扩展应用的真心比较乏力。
比如关于同城的api提供 比较给力,但是你发现豆瓣自己有客户端了。
豆瓣广播,类微博一样,也有了官方的客户端了。
最后觉得用户活跃度最高的小组,却没有提供,同样的一些书影评资讯也只是提供了一个搜索的接口。
我想要一些,比如热门影讯,评论,最后发现只能调用RSS来实现,并且坑爹的单条资讯内容,内容只有描述,没有详情。
不过既然已经做了,就当做练手,上一个项目一直做的网络层,逻辑层,数据处理,这会刚好熟练下UI控件。
下面我们先看下豆瓣关于OAuth2.0中:
豆瓣支持三种OAuth2.0的授权流程:直接在浏览器中运行的Javascript应用的授权流程(user-agent flow)有服务器的WEB应用的授权流程(server-side flow)桌面客户端应用、移动客户端应用的授权流程(native-application flow)
http://developers.douban.com/wiki/?title=oauth2豆瓣文档。
因为ios作为移动客户端应用,我们主要看第三块。熟悉了大致情况后,准备做授权模块。
我们先看下我客户端实现的效果图。
1.首先,我们看文档的api文档描述
flow 与 native-application flow这两种授权流程基本相同,需要通过两步来获取access_token。获取authorization_code通过在浏览器中访问下面的地址,来引导用户授权,并获得authorization_codehttps://www.douban.com/service/auth2/auth参数:参数名称 参数说明client_id 必选参数,应用的唯一标识,对应于APIKeyredirect_uri 必选参数,用户授权完成后的回调地址,应用需要通过此回调地址获得用户的授权结果。此地址必须与在应用注册时填写的回调地址一致。response_type 必选参数,此值可以为 code 或者 token 。在本流程中,此值为 codescope 可选参数,申请权限的范围,如果不填,则使用缺省的scope。如果申请多个scope,使用逗号分隔。state 可选参数,用来维护请求和回调状态的附加字符串,在授权完成回调时会附加此参数,应用可以根据此字符串来判断上下文关系。注意:此请求必须是HTTP GET方式例如:https://www.douban.com/service/auth2/auth? client_id=0b5405e19c58e4cc21fc11a4d50aae64& redirect_uri=https://www.example.com/back& response_type=code& scope=shuo_basic_r,shuo_basic_w返回结果:当用户拒绝授权时,浏览器会重定向到redirect_uri,并附加错误信息https://www.example.com/back?error=access_denied当用户同意授权时,浏览器会重定向到redirect_uri,并附加autorization_codehttps://www.example.com/back?code=9b73a4248
https://www.douban.com/service/auth2/auth就是我们这个授权页面,加载这个页面时,需要在url地址中传入一些参数(应用key啊什么的,相信大家都了解)因此我们需要自己内嵌一个UIWebView控件,(当然,有人会说直接跳转到浏览器不就得了)
这个等会会具体提到,因为我们要截取一个token值。
ps:
这边主要说一下这个重定向地址参数的问题:redirect_uri=https://www.example.com/back
这个参数在申请应用时也会用到,它意义,就当我们在授权页面“授权”或是“拒绝”后,浏览器自动会重定向跳转到这个地址页面,并且在这个url地址中附加了一些
回调信息,这点上面也提到了(比如你点击了拒绝,https://www.example.com/back?error=access_denied,点击了授权,成功的话,就返回token值)
其实这个重定向参数的意义更多我觉得其实是为了web类应用设定的,因为web应用最基础的容器就是一个浏览器,当无论授权或是拒绝后,离开了授权界面,
我们必须提供一个新的地址让浏览器来跳转啊,但是,在移动应用中,其实是并不需要这样的。
因此,你会看到有的资料提示说移动类客户端可以填写“oob”什么的,而且对于移动类客户端最好的授权方式也是如此,并不需要一个重定向地址,直接返回值
不是感觉会更好,这边我们就暂时看api流程提供的来吧。
说了半天,那这个参数到底怎么填呢,(并且豆瓣申请时必须要填,且它还会自动检查格式,必须是url地址)。
考虑到,我们的移动类应用对于这个重定向地址其实并没有实际用处,只是做为一个载体返回一些附加信息,我们会需要这些附加信息。
因此我就根据自个爱好写了一个"https://www.nono_lilith.com";
好了,对于其他几个参数,具体看文档。
比如我的授权url地址+参数的结果:
NSString *urlpath = [NSString stringWithFormat:@"https://www.douban.com/service/auth2/auth?client_id=%@&redirect_uri=%@&response_type=token&display=popup",_api_key,_redirect];.
2.然后就是授权和拒绝操作后的返回了。
按照我们客户端的理念,如果授权成功了,那么我们截取获取授权码保存起来,并给用户显示一个授权成功的提示框,关闭这个授权界面。
同样拒绝也一样,我们获取附加值,判断得知是用户的拒绝操作,同样提示或是关闭该界面。
这边就讲到整片文章的核心点了,对于重定向返回的附加参数的截取。
#pragma mark UIWebViewDelegate methods- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ BOOL b = YES; NSString *targetUrl = request.URL.absoluteString; if ([_douban_register isEqualToString:targetUrl]) {//注册,直接跳转浏览器 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:_douban_register]]; b = NO; }else if ([targetUrl isEqualToString:_resure_url]) {//拒绝授权 b = NO; [self back]; } NSRange range = [targetUrl rangeOfString:@"https://www.nono_lilith.com/#access_token="]; if (range.length > 0) {//点击了授权,并且成功了 NSString *tokenMore = [targetUrl substringFromIndex:range.location+range.length]; NSString *token = [[tokenMore componentsSeparatedByString:@"&"] objectAtIndex:0]; NSLog(@"获取的token = %@",token); _delegate = (NLAppDelegate*)[[UIApplication sharedApplication] delegate]; _delegate.isLogin = YES; _delegate.token = token; b = NO; [self back]; } return b;}- (void)webViewDidStartLoad:(UIWebView *)webView{ }- (void)webViewDidFinishLoad:(UIWebView *)webView{// NSString *url = webView.request.URL.absoluteString; }- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{ }-(void)back{ [self.navigationController popViewControllerAnimated:YES];}
我这边是利用webview的代理方法来实现截取和跳转。
主要操作都在第一个代理方法中。
该方法会返回一个bool值,来控制webview是否要发生请求。
NSString *targetUrl = request.URL.absoluteString;
可以获取webview准备加载的url地址。
先跳过前几行判断注册什么的注释,主要看截取重定向url和他附加的值。
NSRange range = [targetUrl rangeOfString:@"https://www.nono_lilith.com/#access_token="]; if (range.length > 0) {//点击了授权,并且成功了 NSString *tokenMore = [targetUrl substringFromIndex:range.location+range.length]; NSString *token = [[tokenMore componentsSeparatedByString:@"&"] objectAtIndex:0]; NSLog(@"获取的token = %@",token); _delegate = (NLAppDelegate*)[[UIApplication sharedApplication] delegate]; _delegate.isLogin = YES; _delegate.token = token; b = NO; [self back]; }
具体如何来截取其实都是一些微操作,看你自己想法了。只要能实现。
这段代码其实就是捕获重定向截取tokencode。然后bool设置成NO,就是说不用跳转了,或是直接pop或是取消掉该界面。
然后对于用户拒绝操作的判断
else if ([targetUrl isEqualToString:_resure_url]) {//拒绝授权 b = NO; [self back]; }这边的NSString *_resure_url = @"https://www.nono_lilith.com/?error=access_denied";操作基本同上。
以上基本是豆瓣OAuth2.0授权的一种流程。
这边我们还可以做一些小改进。
从页面看到,我们还能点击的两个操作。
1.豆瓣开放平台条款,如果点击就是跳转到豆瓣首页了(目前测试),因为我们的webview没用返回什么的按钮,因此当看完了条款后用户想授权,
发现回不去那个授权网页界面了~~
同样的还有那个注册操作,会跳转到豆瓣注册界面,首先还是会碰到上面说的这点,更重要的一点,豆瓣注册在选择居住地时,我们内嵌的webview不可提供交互
(可能要开启什么属性或是参数,记得Android时候是开始js属性等等),因此,最好和简单的方法就是跳转到safari浏览器执行相关操作。
因此也就是我上面捕获url地址然后进行跳转操作。
以上就是目前豆瓣OAuth2.0移动客户端授权的一种处理方式,因为我看了好多api其实都在完善和测试中。
最后想说,为毛不开放小组API。
- 1楼ztx470539152昨天 16:14
- 能有源码下载地址么