用 Tornado 试玩新浪微博开放平台 API
Tornado 作为一个 Python 的异步非阻塞服务器与轻量级 Web 框架, 相当令人着迷. 为了体验一把 OAuth2.0 认证, 我用 Tornado 搭建了一个网站, 调用新浪微博 API. 新浪微博的 OAuth2.0 认证的顺序如下:
- 用户访问客户端, 客户端把用户带到新浪认证服务器去输用户名密码;
- 新浪认证服务器认证完毕后, 将用户带到客户端某指定页面, 给这个页面传递一个 GET 参数 code;
- 客户端某指定页面接收到 code 之后, 后台发起对新浪API服务器的POST请求, 用 code 换取 access_token;
- 得到 access_token 后, 就可以用来调用各种需要用户登录之后才能调用的 API 了.
下面简单说明在 Python 3 下用 Tornado 如何完成上述四个步骤.
将用户带到新浪认证页面
假定我们要开发的客户端的域名是 dropthej.com , 在新浪新建一个应用, 在设置里填好这个安全域名, 这样才能跨站请求 XMLRequests.
这一步就是写 html 页面, 在 Tornado 中就是写模板. 假设我们在客户端中放置一个按钮叫做 “用新浪微博登陆”, 代码如下:
<form class="form" method="GET" action="https://api.weibo.com/oauth2/authorize"> <input type="hidden" name="client_id" value="这里填你的App Key"/> <input type="hidden" name="redirect_uri" value="http://dropthej.com/auth_code"/> <button type="submit" class="btn btn-info form-control">Login</button> </form>
这样只要一点这个按钮就跑到新浪的认证页面去了, 用户认证好了之后, 新浪会将用户带到你提供的 redirect_uri 地址, 这里就是
http://dropthej.com/auth_code?code=xxxxxxxxxxxxxxxxxxxxxx
所以我们要用 Tornado 来处理这个认证服务器发给我们的 code.
Tornado 后台用 code 去换取 access_token
这一部分有两步工作:
- 得到 code
- 用 code 换 access_token
配置一下 Tornado 的路由表, 让 r’/auth_code’ 路由到 AuthCodeHandler 这个 Handler. 这样我们重写这个 handler 的 get 方法就能获取到 code. 然后我们用 POST 方法把 code 发给新浪, 这里就能体现 Tornado 的异步非阻塞的强大了, Tornado 的 AsyncHTTPClient 能发起异步请求, 用 @gen.coroutine 装饰器可以把异步写得像同步的样子. 代码如下:
from urllib.parse import urlencode import json import tornado.web from tornado import gen from tornado.httpclient import AsyncHTTPClient from handlers.token import TokenBaseHandler class AuthCodeHandler(TokenBaseHandler): """ 已经获得用户授权, 向API服务器获取Token """ @gen.coroutine def get(self): auth_code = self.get_argument("code", "No code") post_data = { "client_id": "你的App Key", "client_secret": "你的App Secret", "grant_type": "authorization_code", "code": auth_code, "redirect_uri": "http://dropthej.com" } http_client = AsyncHTTPClient() response = "init" body = urlencode(post_data) try: response = yield http_client.fetch( "https://api.weibo.com/oauth2/access_token", method="POST", body=body ) except Exception as e: self.write(str(e)) return; token_json = json.loads(str(response.body, encoding='utf-8')) # set token_json self.application.token_json = token_json self.write("<br/><br>" + str(token_json['access_token'])) url = "http://dropthej.com/?tk=" + token_json['access_token'] self.redirect(url)
由于我们仅仅用来玩一玩他的 API, 所以这个得到的 access_token 我们就不写到 cookies 里面去了, 而是采用放在 URL 里面的简单方法. 这样应用的每一个页面都带上 tk 参数, 就能保持用户的登录状态. 这里我们返回到了 http://dropthej.com/?tk=access_token 这个页面, 所以我们在 html 里面接收这个 tk 然后用来调用新浪 API 就可以了.
为什么都是发送 GET 和 POST 请求, 这个要用 Tornado 在后台来发送呢? 在前端用 javascript 来完成不行嘛? 因为这里要把 App Secret 发出去, 人家都叫 Secret 了你还传到前端去经过用户的电脑, 那是相当的不安全. Secret 就是设计来验证这是真正的客户端发出的请求, 所以要在后台发, 要有客户端而不是用户来完成.
使用 jQuery 来调用新浪 API 获取用户最新的首页微博
这不是重点就不多说了, 效果很好很让人开心, 主要代码如下:
var xyz; $(function() { $.ajax({ url: "https://api.weibo.com/2/statuses/home_timeline.json", type: "GET", dataType: "jsonp", data: { "access_token": ac_tk }, success: function(result) { xyz = result.data.statuses; for (x in xyz) { $("#tbody").append("<tr><td>" + xyz[x].user.name + "</td><td>" + xyz[x].text + "</td></tr>"); } } }); });
效果如图所示:
看了你好几篇博文,就像看到我以前的样子。。(以前西电ACM的,现在出国了)。楼主加油!
谢谢鼓励!
楼主如果可以制作一个订阅就好了 可以订阅你这里发的文章
用各种 RSS订阅工具 可以订阅哦,我就用来订阅了很多博客。推荐newszeit 以及 inoreader。你可以试试。
ACM金牌嘛
不错不错,来看看。。
[路过这儿] 新手~学习起来~~~~~
新手~学习起来~~~~~