如何从笔记本访问当前用户/auth_state



我正在使用带有自定义验证器的JupyterHub。它使用访问令牌设置auth_state,然后可以将其复制到pre_spawn_start方法内的环境中,如示例所示:

class MyAuthenticator(Authenticator):
@gen.coroutine
def authenticate(self, handler, data=None):
username = yield identify_user(handler, data)
upstream_token = yield token_for_user(username)
return {
'name': username,
'auth_state': {
'upstream_token': upstream_token,
},
}
@gen.coroutine
def pre_spawn_start(self, user, spawner):
"""Pass upstream_token to spawner via environment variable"""
auth_state = yield user.get_auth_state()
if not auth_state:
# auth_state not enabled
return
spawner.environment['UPSTREAM_TOKEN'] = auth_state['upstream_token']

但是,每个用户只发生一次。如果我注销并再次登录,则不会再次调用pre_spawn_start,并且环境变量中仍然存在旧令牌。

是否可以直接从笔记本访问user.get_auth_state(),以便确保使用当前令牌,而不是以前设置并存储在环境中?

否则,是否可以在注销时强制spawner停止,以便后续登录将触发pre_spawn_start

您可以强制停止服务器,并在令牌过期时要求登录,这可以通过以下步骤实现,

  1. 编写refresh_user方法以获取新令牌(附带示例代码(
  2. 设置refresh_user的时间。
    • c.MyAuthenticator.auth_refresh_age=30#这可能是令牌的有效时间(以秒为单位(
import inspect, concurrent,asyncio
async def refresh_user(self, user,handler=None):
"""
1. Check if token is valid and then call _shutdown_servers and then redirect to login page
2. If time of refresh_user is set as token expiry, directly call _shutdown_servers and then redirect to login page
This is shutdown single user servers and once redirected to login, auth flow gets run and new tokens are passed to spawner
"""
auth_state = await user.get_auth_state()
if self._is_invalid_sessionid(auth_state):
await self._shutdown_servers(user, handler=None)
handler.clear_login_cookie()
handler.redirect('/login')
return True
async def maybe_future(obj):
"""Return an asyncio Future
Use instead of gen.maybe_future
For our compatibility, this must accept:
- asyncio coroutine (gen.maybe_future doesn't work in tornado < 5)
- tornado coroutine (asyncio.ensure_future doesn't work)
- scalar (asyncio.ensure_future doesn't work)
- concurrent.futures.Future (asyncio.ensure_future doesn't work)
- tornado Future (works both ways)
- asyncio Future (works both ways)
"""
if inspect.isawaitable(obj):
# already awaitable, use ensure_future
return asyncio.ensure_future(obj)
elif isinstance(obj, concurrent.futures.Future):
return asyncio.wrap_future(obj)
else:
# could also check for tornado.concurrent.Future
# but with tornado >= 5.1 tornado.Future is asyncio.Future
f = asyncio.Future()
f.set_result(obj)
return f
async def _shutdown_servers(self, user,handler):
"""Shutdown servers for logout
Get all active servers for the provided user, stop them.
"""
active_servers = [
name
for (name, spawner) in user.spawners.items()
if spawner.active and not spawner.pending
]
if active_servers:
self.log.info("Shutting down %s's servers", user.name)
futures = []
for server_name in active_servers:
futures.append(self.maybe_future(handler.stop_single_user(user, server_name)))
await asyncio.gather(*futures)

https://jupyterhub.readthedocs.io/en/stable/api/auth.html#jupyterhub.auth.Authenticator.auth_refresh_agehttps://jupyterhub.readthedocs.io/en/stable/api/auth.html#jupyterhub.auth.Authenticator.refresh_user

似乎这个c.Authenticator.refresh_pre_spawn=True,正如Eos Antigen所建议的那样,解决了这个问题:每次你再次登录时,预生成定义的函数都会再次执行。

最新更新