在自定义 Jupyterhub 验证器中设置 spawner 环境变量

Set spawner environment variables in custom Jupyterhub authenticator

我正在尝试使用 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']

我的自定义处理程序没有 return 任何东西,它会重定向 - 这可能就是为什么身份验证方法 return 是 NotImplementedError.

的原因

我缺少什么可以让我在现有代码中使用 pre_spawn_start 挂钩?

方法是实现 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']