zoukankan      html  css  js  c++  java
  • 升级Tornado到4后weibo oauth登录不了

    把 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']
                    )
  • 相关阅读:
    LVM
    linux在线添加硬盘、扫盘
    django 的用户认证组件
    django组件-cookie与session
    django组件 分页器
    Django 与 Ajax
    Djange 模型层2
    Django 模型层
    Djange 的模板层
    Django的视图层
  • 原文地址:https://www.cnblogs.com/myx/p/python_weibo_oauth.html
Copyright © 2011-2022 走看看