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

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 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']
                )