Tornado - 从等待中获取 return 值(多个回调)
Tornado - getting return value from await (multiple callbacks)
我正在开发一个在 tornado 中使用 OAuth2 身份验证的应用程序。登录 class 如下所示:
class IDPLogin(tornado.web.RequestHandler, IDPLoginHandler):
async def get(self):
if self.get_argument('code', False):
access = await self.get_authenticated_user(
...
)
print(type(access))
#self.set_secure_cookie('user', self.get_argument('code'))
#self.redirect('/')
else:
await self.authorize_redirect(
...
)
使用 get_authenticated_user 方法如下所示(两个额外的回调,用于获取评估用户所需的所有详细信息):
class IDPHubLoginHandler(tornado.auth.OAuth2Mixin):
def __init__(self):
self._OAUTH_AUTHORIZE_URL = "..."
self._OAUTH_ACCESS_TOKEN_URL = "..."
self._USERINFO_ENDPOINT = "..."
async def get_authenticated_user(self, redirect_uri, client_id, client_secret, code):
http = self.get_auth_http_client()
body = urllib_parse.urlencode({
"redirect_uri": redirect_uri,
"code": code,
"client_id": client_id,
"client_secret": client_secret,
"grant_type": "authorization_code",
})
fut = http.fetch(self._OAUTH_ACCESS_TOKEN_URL,
method="POST",
headers={'Content-Type': 'application/x-www-form-urlencoded'},
body=body)
fut.add_done_callback(wrap(functools.partial(self._on_access_token)))
def _on_access_token(self, future):
"""Callback function for the exchange to the access token."""
try:
response = future.result()
except Exception as e:
future.set_exception(AuthError('IDP auth error: %s' % str(e)))
return
args = escape.json_decode(response.body)
# Fetch userinfo
http = self.get_auth_http_client()
fut = http.fetch(self._USERINFO_ENDPOINT,
method="GET",
headers={
'Authorization': 'Bearer ' + args['access_token'],
'accept': 'application/json'
}
)
fut.add_done_callback(wrap(functools.partial(self._on_userinfo)))
def _on_userinfo(self, future):
response = future.result()
r_body = escape.json_decode(response.body)
return r_body
我希望能够在 _on_userinfo 回调中访问正文 returned,但是登录 class 中的 access 是 'NoneType' 并且我想评估响应以拒绝访问或向用户提供 cookie。
提供的代码成功获取了所有必需的输入数据,但是我很难理解如何从回调中获取 return 值并在主登录 class (IDPLogin) 中重用它们。我查看了 Tornado 文档,但找不到答案。 Oauth2/OpenID 示例充其量只是非常简短的细节。
尝试set_result asyncio.base_futures.InvalidStateError 的未来结果。
找到了另一种方法。不确定这是否是最规范的做法,但似乎可以完成工作。
实现Oauth2 Mixin如下:
class IDPLoginHandler(tornado.auth.OAuth2Mixin):
...
async def get_authenticated_user(self, redirect_uri, client_id, client_secret, code):
#do fetching and return future result
async def get_user_info(self, access_token):
#do fetching and return future result
从主登录处理程序使用 await 关键字顺序调用方法:
class IDPLogin(tornado.web.RequestHandler, IDPLoginHandler):
async def get(self):
if self.get_argument('code', False):
response_token = await self.get_authenticated_user(
...
)
token = escape.json_decode(response_token.body)['access_token']
response_userinfo = await self.get_user_info(token)
我正在开发一个在 tornado 中使用 OAuth2 身份验证的应用程序。登录 class 如下所示:
class IDPLogin(tornado.web.RequestHandler, IDPLoginHandler):
async def get(self):
if self.get_argument('code', False):
access = await self.get_authenticated_user(
...
)
print(type(access))
#self.set_secure_cookie('user', self.get_argument('code'))
#self.redirect('/')
else:
await self.authorize_redirect(
...
)
使用 get_authenticated_user 方法如下所示(两个额外的回调,用于获取评估用户所需的所有详细信息):
class IDPHubLoginHandler(tornado.auth.OAuth2Mixin):
def __init__(self):
self._OAUTH_AUTHORIZE_URL = "..."
self._OAUTH_ACCESS_TOKEN_URL = "..."
self._USERINFO_ENDPOINT = "..."
async def get_authenticated_user(self, redirect_uri, client_id, client_secret, code):
http = self.get_auth_http_client()
body = urllib_parse.urlencode({
"redirect_uri": redirect_uri,
"code": code,
"client_id": client_id,
"client_secret": client_secret,
"grant_type": "authorization_code",
})
fut = http.fetch(self._OAUTH_ACCESS_TOKEN_URL,
method="POST",
headers={'Content-Type': 'application/x-www-form-urlencoded'},
body=body)
fut.add_done_callback(wrap(functools.partial(self._on_access_token)))
def _on_access_token(self, future):
"""Callback function for the exchange to the access token."""
try:
response = future.result()
except Exception as e:
future.set_exception(AuthError('IDP auth error: %s' % str(e)))
return
args = escape.json_decode(response.body)
# Fetch userinfo
http = self.get_auth_http_client()
fut = http.fetch(self._USERINFO_ENDPOINT,
method="GET",
headers={
'Authorization': 'Bearer ' + args['access_token'],
'accept': 'application/json'
}
)
fut.add_done_callback(wrap(functools.partial(self._on_userinfo)))
def _on_userinfo(self, future):
response = future.result()
r_body = escape.json_decode(response.body)
return r_body
我希望能够在 _on_userinfo 回调中访问正文 returned,但是登录 class 中的 access 是 'NoneType' 并且我想评估响应以拒绝访问或向用户提供 cookie。
提供的代码成功获取了所有必需的输入数据,但是我很难理解如何从回调中获取 return 值并在主登录 class (IDPLogin) 中重用它们。我查看了 Tornado 文档,但找不到答案。 Oauth2/OpenID 示例充其量只是非常简短的细节。
尝试set_result asyncio.base_futures.InvalidStateError 的未来结果。
找到了另一种方法。不确定这是否是最规范的做法,但似乎可以完成工作。
实现Oauth2 Mixin如下:
class IDPLoginHandler(tornado.auth.OAuth2Mixin): ... async def get_authenticated_user(self, redirect_uri, client_id, client_secret, code): #do fetching and return future result async def get_user_info(self, access_token): #do fetching and return future result
从主登录处理程序使用 await 关键字顺序调用方法:
class IDPLogin(tornado.web.RequestHandler, IDPLoginHandler): async def get(self): if self.get_argument('code', False): response_token = await self.get_authenticated_user( ... ) token = escape.json_decode(response_token.body)['access_token'] response_userinfo = await self.get_user_info(token)