惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Hacker News
The Hacker News
F
Full Disclosure
Cloudbric
Cloudbric
Blog — PlanetScale
Blog — PlanetScale
W
WeLiveSecurity
N
News and Events Feed by Topic
T
Troy Hunt's Blog
V2EX - 技术
V2EX - 技术
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
B
Blog
GbyAI
GbyAI
C
Check Point Blog
B
Blog RSS Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Recorded Future
Recorded Future
The Last Watchdog
The Last Watchdog
N
News and Events Feed by Topic
T
The Blog of Author Tim Ferriss
O
OpenAI News
V
V2EX
人人都是产品经理
人人都是产品经理
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
WordPress大学
WordPress大学
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Security @ Cisco Blogs
C
Cisco Blogs
Security Latest
Security Latest
S
Security Affairs
V
Visual Studio Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Azure Blog
Microsoft Azure Blog
Last Week in AI
Last Week in AI
AWS News Blog
AWS News Blog
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
PCI Perspectives
PCI Perspectives
博客园_首页
U
Unit 42
Google DeepMind News
Google DeepMind News
Hugging Face - Blog
Hugging Face - Blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
The Register - Security
The Register - Security
N
Netflix TechBlog - Medium
L
LINUX DO - 热门话题
H
Hacker News: Front Page

博客园 - myx

安装gitlab管理自己的代码 SQL Server 无日志文件附加数据库 用monit监控系统关键进程 Failed to read auto-increment value from storage engine错误的处理方法 今天测试了一下 sqlalchemy 性能 PIL The _imaging C module is not installed phpExcel大数据量情况下内存溢出解决 tcpdf慢及常用的一些方法及问题 Python获取WebService CodeIgniter出现Disallowed Key Characters的问题 CodeIgniter链接ms sql 如果数据库名称有点号连接出错 用python写windows服务 CodeIgniter链接ms sql 的过程windows 2008 关于NTLM认证的.NET,php,python登录 DotNetOpenAuth的Facebook登录,获取头像与基本资料 php里的html内容切取 js生成新加坡的NRIC号码 Sina站内应用的登录 PowerDesigner 链接MySql 用ODBC链接不上的问题
升级Tornado到4后weibo oauth登录不了
myx · 2014-11-12 · via 博客园 - myx

把 Tornado 升级到4后,发现正常运行的微博登录不可以了。

原因是4已经移除 RequestHandler.async_callback and WebSocketHandler.async_callback ,具体见 http://www.tornadoweb.org/en/stable/releases/v4.0.0.html

替换成 functools.partial 就可解决

记得需要先 

import functools

修改后的Weibo.py如下

# -*- coding: utf-8 -*-
import functools
from tornado import gen
from tornado import httpclient
from tornado import escape
from tornado.httputil import url_concat
from tornado.concurrent import Future
from tornado.auth import OAuth2Mixin, _auth_return_future, AuthError

try:
    import urlparse
except ImportError:
    import urllib.parse as urlparse

try:
    import urllib.parse as urllib_parse
except ImportError:
    import urllib as urllib_parse

class WeiboMixin(OAuth2Mixin):
    _OAUTH_ACCESS_TOKEN_URL = 'https://api.weibo.com/oauth2/access_token'
    _OAUTH_AUTHORIZE_URL = 'https://api.weibo.com/oauth2/authorize?'
    
    @_auth_return_future
    def get_authenticated_user(self, redirect_uri, client_id, client_secret, code, callback, grant_type='authorization_code', extra_fields=None):
        http = self.get_auth_http_client()
        args = {
            'redirect_uri': redirect_uri,
            'code': code,
            'client_id': client_id,
            'client_secret': client_secret,
            'grant_type': grant_type,
            }

        fields = set(['id', 'screen_name', 'profile_image_url'])

        if extra_fields:
            fields.update(extra_fields)

        # self.async_callback
        http.fetch(self._OAUTH_ACCESS_TOKEN_URL, method='POST', 
                   body=urllib_parse.urlencode(args),
                   callback=functools.partial(self._on_access_token, redirect_uri, client_id, client_secret, callback, fields))

    def _oauth_request_token_url(self, redirect_uri=None, client_id=None,
                                 client_secret=None, code=None,
                                 grant_type=None, extra_params=None):
        pass

    
    def _on_access_token(self, redirect_uri, client_id, client_secret,
                         future, fields, response):
        if response.error:
            future.set_exception(AuthError('Weibo auth error %s' % str(response)))
            return

        args = escape.json_decode(escape.native_str(response.body))
        session = {
            'access_token': args['access_token'],
            'expires': args['expires_in'],
            'uid': args['uid'],
            }

        # self.async_callback
        self.weibo_request(
            path='/users/show.json',
            callback=functools.partial(
                self._on_get_user_info, future, session, fields),
            access_token=session['access_token'],
            uid=session['uid']
            )

    def _on_get_user_info(self, future, session, fields, user):
        if user is None:
            future.set_result(None)
            return

        fieldmap = {}
        for field in fields:
            fieldmap[field] = user.get(field)
        
        fieldmap.update({'access_token': session['access_token'], 'session_expires': session['expires']})

        future.set_result(fieldmap)

    @_auth_return_future
    def weibo_request(self, path, callback, access_token=None, uid=None, post_args=None, **args):
        url = "https://api.weibo.com/2" + path
        all_args = {}
        if access_token:
            all_args['access_token'] = access_token
        if uid:
            all_args['uid'] = uid
        if args:
            all_args.update(args)

        if all_args:
            url += '?' + urllib_parse.urlencode(all_args)
        # self.async_callback
        callback = functools.partial(self._on_weibo_request, callback)
        http = self.get_auth_http_client()
        if post_args is not None:
            http.fetch(url, method="POST", body=urllib_parse.urlencode(post_args),
                       callback=callback)
        else:
            http.fetch(url, callback=callback)

    def _on_weibo_request(self, future, response):
        if response.error:
            future.set_exception(AuthError('Error response %s fetching %s',
                                           response.error, response.request.url))

            return

        future.set_result(escape.json_decode(response.body))
    
    def get_auth_http_client(self):
        return httpclient.AsyncHTTPClient()

登录代码

class WeiboAuthHandler(SNSBaseHandler, WeiboMixin):
    @tornado.web.asynchronous
    @gen.coroutine
    def get(self):
        if self.get_argument('code', None):
            user = yield self.get_authenticated_user(
                redirect_uri=self.request.full_url(), 
                client_id=self.settings['weibo_api_key'],
                client_secret=self.settings['weibo_api_secret'],
                code=self.get_argument('code'))
            
            snsId = user['id']
            email = '%s@weibo.com' % snsId
            nickname = user['screen_name']
            profileImg= 'http://tp1.sinaimg.cn/%s/180/0/1' % snsId
            session_expires = int(time.time()) + int(user['session_expires'])
            result,tp,userId = self.SNSUser(self.SNSType['weibo'],email,nickname,snsId,user['access_token'],json.dumps(user),session_expires,profileImg)
            if result:
                expiresDays = int(user['session_expires'])/(3600*24)
                expiresDays = expiresDays < 1 and 1 or expiresDays
                self.userLogin(userId,expiresDays)
                url_next=self.get_argument("next", "/")
                self.redirect(url_next)
            else:
                self.redirect('/login')
        else:
            self.authorize_redirect(
                redirect_uri=self.request.full_url(),
                client_id=self.settings['weibo_api_key']
                )