4

我一直在尝试使用我的 Login Rest API 而不是其他类型进行身份验证。如何做到这一点?REMOTE_USER 身份验证是正确的方法吗?如果是这样,我可以获得有关此的示例代码或文档吗?

阅读此处的文档,但由于我是 flask-appbuilder 和 python 的新手,所以不太了解。

4

2 回答 2

2

只为下一个到达这里的人。

遵循此处的说明:https ://superset.incubator.apache.org/installation.html#middleware

但不起作用:重定向太多。

Flask App-Builder 代码: https ://github.com/dpgaspar/Flask-AppBuilder/blob/167c13ec6dda6e7d8286e590233cd603a7d13928/flask_appbuilder/security/views.py#L728

终于做了我自己的自定义远程登录(草稿版如下)。

# Apache superset REMOTE_USER authentication
# https://superset.incubator.apache.org/installation.html#middleware
from flask_appbuilder.security.manager import AUTH_REMOTE_USER

# Define AUTH_TYPE
# AUTH_TYPE = AUTH_REMOTE_USER

# Allow users to auto register and be assigned to Remote role
# AUTH_USER_REGISTRATION = True
# AUTH_USER_REGISTRATION_ROLE = "Remote"

# For testing without a proxy just calling http://localhost:9000/superset/welcome?logme=user1
from flask import request, g
from flask_login import login_user, logout_user
import logging


# Middleware to extract user from header HTTP_X_PROXY_REMOTE_USER
# and place it at REMOTE_USER
class RemoteUserLogin(object):

    def __init__(self, app):
        self.app = app

    def log_user(self, environ):
        from superset import security_manager as sm

        username = self.get_username(environ)
        logging.info("REMOTE_USER Checking logged user")
        if hasattr(g, "user") and \
            hasattr(g.user, "username"):
            if g.user.username == username:
                logging.info("REMOTE_USER user already logged")
                return g.user
            else:
                logout_user()

        user = sm.find_user(username=username)
        logging.info("REMOTE_USER Look up user: %s", user)
        if user:
            logging.info("REMOTE_USER Login_user: %s", user)
            login_user(user)
        return user

    def get_username(self, environ):
        user = environ.pop('HTTP_X_PROXY_REMOTE_USER', None)

        if not user and self.app.debug:
             # Dev hack 
            user = environ.get("werkzeug.request").args.get("logme")
            if user:
                logging.error("Logging user from request. Remove me ASAP!!!: %s", user)

        environ['REMOTE_USER'] = user
        return user

    def before_request(self):
        user = self.log_user(request.environ)
        if not user:
            raise Exception("Invalid login or user not found")


from superset.app import SupersetAppInitializer
def app_init(app):
    logging.info("Resgistering RemoteUserLogin")
    app.before_request(RemoteUserLogin(app).before_request)
    return SupersetAppInitializer(app)

APP_INITIALIZER = app_init
于 2020-04-08T20:34:02.980 回答
1

对于简单的情况,将以下代码段添加到此处superset_config.py提到的:

class RemoteUserMiddleware(object):
    def __init__(self, app):
        self.app = app
    def __call__(self, environ, start_response):
        user = environ.pop('HTTP_X_PROXY_REMOTE_USER', None)
        environ['REMOTE_USER'] = user
        return self.app(environ, start_response)

ADDITIONAL_MIDDLEWARE = [RemoteUserMiddleware, ]
AUTH_TYPE = AUTH_REMOTE_USER
AUTH_USER_REGISTRATION = True

并配置反向代理以将用户名(或电子邮件)添加到名为X-PROXY-REMOTE-USER(不带HTTP)的标头中。启用AUTH_USER_REGISTRATION很重要,以便在帐户不存在时自动创建帐户。

这将调用AuthRemoteUserView视图,该视图又调用auth_user_remote_user来查找并创建一个用户(如果它不存在)。

如果你想自定义它来添加电子邮件、用户名,并且可能基于组做 rbac,你可以像这样扩展上面的视图:

class CustomRemoteUserView(AuthRemoteUserView):
    [...]

class CustomSecurityManager(SupersetSecurityManager):
    authremoteuserview = CustomRemoteUserView

CUSTOM_SECURITY_MANAGER = CustomSecurityManager

于 2022-01-08T16:33:35.980 回答