python - 如何使用 GoogleOAuth2Mixin 使用 tornado 3.2.2 进行谷歌登录授权

标签 python oauth-2.0 tornado google-oauth

我正在尝试为我的 tornado 应用实现 Google Oauth 2.0 登录。他们对 3.2.2 进行了一些更改,但似乎没有明确的说明。以下是我的代码:

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        user = self.get_secure_cookie('trakr')
        if not user: return None
        return True

class ProductsHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.render("products.html")
        return

class GAuthLoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    @tornado.gen.coroutine
    def get(self):
        if self.get_current_user():
            self.redirect('/products')
            return

        if self.get_argument('code', False):
            user = yield self.get_authenticated_user(redirect_uri=settings.google_redirect_url,
                code=self.get_argument('code'))
            if not user:
                self.clear_all_cookies() 
                raise tornado.web.HTTPError(500, 'Google authentication failed')

            access_token = str(user['access_token'])
            http_client = self.get_auth_http_client()
            http_client.fetch('https://www.googleapis.com/oauth2/v1/userinfo?access_token='+access_token, self._save_user_profile)
            return

        elif self.get_secure_cookie('trakr'):
            self.redirect('/products')
            return

        else:
            yield self.authorize_redirect(
                redirect_uri=settings.google_redirect_url,
                client_id=self.settings['google_oauth']['key'],
                scope=['email'],
                response_type='code',
                extra_params={'approval_prompt': 'auto'})

    def _save_user_profile(self, response):
        if not response:
            raise tornado.web.HTTPError(500, "Google authentication failed.")
        user = json.loads(response.body)
        self.set_secure_cookie('trakr', user['email']) 
        self.redirect('/products')

目前我遇到以下错误:

[E 140702 12:35:30 ioloop:491] Exception in callback <functools.partial object at 0xa51ff54>
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/dist-packages/tornado/ioloop.py", line 477, in _run_callback
        callback()
      File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 331, in wrapped
        raise_exc_info(exc)
      File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 302, in wrapped
        ret = fn(*args, **kwargs)
      File "main.py", line 202, in _save_user_profile
        self.redirect('/')
      File "/usr/local/lib/python2.7/dist-packages/tornado/web.py", line 629, in redirect
        raise Exception("Cannot redirect after headers have been written")
    Exception: Cannot redirect after headers have been written

我不明白我在哪里设置响应 header 。

  • 如何解决这个问题?
  • 我这样做对吗?你有任何示例代码吗?

最佳答案

如果有人在看,这是本回答后的脚本:

class GAuthLoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    @tornado.gen.coroutine
    def get(self):
        if self.get_current_user():
            self.redirect('/products')
            return

        if self.get_argument('code', False):
            user = yield self.get_authenticated_user(redirect_uri=settings.google_redirect_url,
                code=self.get_argument('code'))
            if not user:
                self.clear_all_cookies() 
                raise tornado.web.HTTPError(500, 'Google authentication failed')

            access_token = str(user['access_token'])
            http_client = self.get_auth_http_client()
            response =  yield http_client.fetch('https://www.googleapis.com/oauth2/v1/userinfo?access_token='+access_token)
            if not response:
                self.clear_all_cookies() 
                raise tornado.web.HTTPError(500, 'Google authentication failed')
            user = json.loads(response.body)
            # save user here, save to cookie or database
            self.set_secure_cookie('trakr', user['email']) 
            self.redirect('/products')
            return

        elif self.get_secure_cookie('trakr'):
            self.redirect('/products')
            return

        else:
            yield self.authorize_redirect(
                redirect_uri=settings.google_redirect_url,
                client_id=self.settings['google_oauth']['key'],
                scope=['email'],
                response_type='code',
                extra_params={'approval_prompt': 'auto'})

关于python - 如何使用 GoogleOAuth2Mixin 使用 tornado 3.2.2 进行谷歌登录授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24536768/

相关文章:

python - scons -u 和 variantdirs

c# - 在 WP7 上使用 Google oAuth

python - Tornado 长轮询请求

python - 我可以使用 Tornado+Celery+RabbitMQ+Redis 吗?

python - 有没有一种使用范围创建元组列表的有效方法?

python - 控制线程类python中的循环

Python Plotly 条形图对 csv 中的项目进行计数

c# - Web Api 项目中的 MVC 应用程序 Cookie 和 token 身份验证

c# - 使用 Thinktecture Identity Server 时保留 OAuth2 不记名 token

python - Tornado url 正则表达式 unicode 字符