我正在尝试为我的龙卷风应用实施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
我不明白我在哪里设置响应标头。
答案 0 :(得分:5)
如果有人在看,这是Ben回答后的剧本:
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'})
答案 1 :(得分:1)
不要混合协程和回调样式。 http_client.fetch
块末尾的if self.get_argument('code')
调用应使用yield和no callback参数(然后在返回之前内联_save_user_profile
方法)