我正在尝试为Jupyterhub使用远程身份验证插件,但也要使用它来将数据保存到生成用户的auth_state
属性中。
在Remote User Authenticator的基础上,我发挥了很大的作用,使我可以创建用户并通过读取查询参数来创建会话。
import os
import pprint
from jupyterhub.handlers import BaseHandler
from jupyterhub.auth import Authenticator
from jupyterhub.utils import url_path_join
from tornado import gen, web
from traitlets import Unicode
class InkspotUserLoginHandler(BaseHandler):
def get(self):
inkspot_user = self.get_argument('user', None, True)
inkspot_study = self.get_argument('studyFolder', None, True)
if inkspot_user == "":
raise web.HTTPError(401)
if inkspot_study == "":
raise web.HTTPError(401)
user = self.user_from_username(inkspot_user)
self.set_login_cookie(user)
next_url = self.get_next_url(user)
self.redirect(next_url)
class InkspotUserAuthenticator(Authenticator):
"""
Accept the authenticated user name from the user query parameter.
"""
def get_handlers(self, app):
return [
(r'/login', InkspotUserLoginHandler),
]
@gen.coroutine
def authenticate(self, handler, data):
raise NotImplementedError()
但是,我需要根据发送到身份验证器的其他查询参数在生成器中设置环境变量。我已经在文档中看到了code example,该文档将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']
我的自定义处理程序不返回任何内容,它会重定向-这可能是authenticate方法返回NotImplementedError
的原因。
我缺少什么让我可以在现有代码中使用pre_spawn_start
钩子?
答案 0 :(得分:0)
方法是实现authenticate方法并将查询参数作为数据字典传递给它。
import os
import pprint
from jupyterhub.handlers import BaseHandler
from jupyterhub.auth import Authenticator
from jupyterhub.utils import url_path_join
from tornado import gen, web
from traitlets import Unicode
class InkspotUserLoginHandler(BaseHandler):
@gen.coroutine
def get(self):
inkspot_user = self.get_argument('user', None, True)
inkspot_study = self.get_argument('studyFolder', None, True)
if inkspot_user == "":
raise web.HTTPError(401)
if inkspot_study == "":
raise web.HTTPError(401)
userDict = {
'name': inkspot_user,
'studyFolder': inkspot_study
}
user = yield self.login_user(userDict)
next_url = self.get_next_url(user)
self.redirect(next_url)
class InkspotUserAuthenticator(Authenticator):
"""
Accept the authenticated user name from the user query parameter.
"""
def get_handlers(self, app):
return [
(r'/login', InkspotUserLoginHandler),
]
@gen.coroutine
def authenticate(self, handler, data):
return {
'name': data['name'],
'auth_state': {
'studyFolder': data['studyFolder']
}
}
@gen.coroutine
def pre_spawn_start(self, user, spawner):
"""Pass inkspot data to spawner via environment variable"""
auth_state = yield user.get_auth_state()
if not auth_state:
# auth_state not enabled
self.log.debug('auth_state not enabled')
return
spawner.environment['STUDY_FOLDER'] = auth_state['studyFolder']