Tornado Auth(Twittermixin)问题

时间:2015-12-22 02:30:01

标签: python oauth tornado

我目前正在尝试使用龙卷风来显示我的推文流。以下是我的代码:

#!/usr/bin/env python
import time
import logging
from tornado.auth import TwitterMixin
from tornado.escape import json_decode, json_encode
from tornado.ioloop import IOLoop
from tornado import gen
from tornado.options import define, options, parse_command_line, parse_config_file
from tornado.web import Application, RequestHandler, authenticated, HTTPError

define('port', default=8080, help="port to listen on")
define('config_file', default='secrets.cfg',
       help='filename for additional configuration')

define('debug', default=True, group='application',
       help="run in debug mode (with automatic reloading)")
# The following settings should probably be defined in secrets.cfg
define('twitter_consumer_key', type=str, group='application')
define('twitter_consumer_secret', type=str, group='application')
define('cookie_secret', type=str, group='application',
       default='this is a string',
       help="signing key for secure cookies")

class BaseHandler(RequestHandler):
    COOKIE_NAME = "uuser"
    def get_current_user(self):
        user_json = self.get_secure_cookie(self.COOKIE_NAME)
        if not user_json:
            print("  No user_json")
            return None
        print("  Yes user_json")
        return json_decode(user_json)

class MainHandler(BaseHandler, TwitterMixin):
    @authenticated
    @gen.coroutine
    def get(self):
        timeline = yield self.twitter_request(
            '/statuses/home_timeline',
            access_token = self.current_user['access_token'])
        self.render('home.html', timeline=timeline)

class LoginHandler(BaseHandler, TwitterMixin):
    @gen.coroutine
    def get(self):
        if self.get_argument('oauth_token', None):
            user = yield self.get_authenticated_user()
            print('  user:', type(user))
            del user["description"]
            self.set_secure_cookie(self.COOKIE_NAME, json_encode(user))
            print('  get_secure_cookie:', self.get_secure_cookie(self.COOKIE_NAME) )
            self.redirect(self.get_argument('next', '/'))
        else:
            print("  Authorize_redirecting...")
            yield self.authorize_redirect(callback_uri=self.request.full_url())

class LogoutHandler(BaseHandler):
    def get(self):
        self.clear_cookie("user")

def main():
    parse_command_line(final=False)
    parse_config_file(options.config_file)

    app = Application(
        [
            (r'/', MainHandler),
            (r'/login', LoginHandler),
            (r'/logout', LogoutHandler),
        ],
        login_url='/login',
        **options.group_dict('application'))
    app.listen(options.port)

    logging.info('Listening on http://localhost:%d' % options.port)
    IOLoop.current().start()

if __name__ == '__main__':
    main()

所以我对流程的理解如下:

1。)访问' /' - MainHandler,如果用户未登录,@authenticated将重定向到login_url

2。)访问' / login' - LoginHandler,self.authorize_redirect(callback_uri=self.request.full_url())会在网址末尾添加oauth_token参数,然后重新访问' / login'

3。)访问' / login' - LoginHandler,从self.get_authenticated_user()set_secure_cookie(self.COOKIE_NAME, json_encode(user))

获取用户

这就是我认为的问题,我似乎无法设置cookie。当我尝试通过self.get_secure_cookie(self.COOKIE_NAME)立即访问它时,会返回None,因此会继续重新访问' / login'

有人能为我的问题提供一些帮助吗?也许这是我看不到的非常明显的事情。感谢

我还在我的Twitter应用设置中将http://127.0.0.1:8080/设置为回调网址,不确定这是否对此问题有任何贡献。

1 个答案:

答案 0 :(得分:-2)

最终解决方案!!

#!/usr/bin/env python
import time
import uuid
import logging
from tornado.auth import TwitterMixin
from tornado.escape import json_decode, json_encode, url_escape, url_unescape
from tornado.ioloop import IOLoop
from tornado import gen
from tornado.options import define, options, parse_command_line, parse_config_file
from tornado.web import Application, RequestHandler, authenticated, HTTPError
from urllib.parse import quote
import re

define('port', default=8080, help="port to listen on")
define('config_file', default='secrets.cfg',
       help='filename for additional configuration')

define('debug', default=True, group='application',
       help="run in debug mode (with automatic reloading)")
# The following settings should probably be defined in secrets.cfg
define('twitter_consumer_key', type=str, group='application')
define('twitter_consumer_secret', type=str, group='application')
# define('cookie_secret', type=str, group='application',
#        default='thisisastring',
#        help="signing key for secure cookies")


class BaseHandler(RequestHandler):
    COOKIE_NAME = "user"
    def get_current_user(self):
        user_json = self.get_cookie(self.COOKIE_NAME)
        if not user_json:
            print("\n  - Cannot obtain cookie from client browser")
            return None
        print("\n  - Cookie obtained from client browser")
        return json_decode(user_json)

class MainHandler(BaseHandler, TwitterMixin):
    @authenticated
    @gen.coroutine
    def get(self):
        print("\n  - Obtaining timeline from twitter")
        timeline = yield self.twitter_request(
            '/statuses/home_timeline',
            access_token = self.current_user)
        self.render('home.html', timeline=timeline)

class LoginHandler(BaseHandler, TwitterMixin):
    @gen.coroutine
    def get(self):
        if self.get_argument('oauth_token', None):
            print("\n  - Authenticating with oauth_token...")
            user = yield self.get_authenticated_user()
            encoded_token = json_encode(user['access_token'])

            # remove certain ascii symbols which are rejected  
            # by self.set_cookie() function...
            encoded_token = re.sub(r"[\x00-\x20]", '', encoded_token)

            # save encoded token as cookie  
            self.set_cookie(name=self.COOKIE_NAME, value=encoded_token)
            self.redirect(self.get_argument('next', '/'))
        else:
            print("\n  - Authorize_redirecting...")
            yield self.authorize_redirect(callback_uri=self.request.full_url())

class LogoutHandler(BaseHandler):
    def get(self):
        self.clear_cookie(self.COOKIE_NAME)

def main():
    parse_command_line(final=False)
    parse_config_file(options.config_file)

    app = Application(
        [
            (r'/', MainHandler),
            (r'/login', LoginHandler),
            (r'/logout', LogoutHandler),
        ],
        login_url='/login',
        cookie_secret=str(uuid.uuid4().bytes),
        **options.group_dict('application'))
    app.listen(options.port)

    logging.info('Listening on http://localhost:%d' % options.port)
    IOLoop.current().start()

if __name__ == '__main__':
    main()