Подход для предотвращения анномного доступа к сайту CKAN - PullRequest
0 голосов
/ 25 июня 2019

У меня есть сайт CKAN, работающий с настроенным расширением ckanext-ldap, но я не хочу, чтобы только авторизованные пользователи имели доступ к сайту.

Это мое решение, но я не совсем доволен:

import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit

def site_read(context, data_dict):
    # List of allowed paths, when not logged in
    allowed_anon_paths = ['/user/login', '/ldap_login_handler']

    # Prevent "site read" if the user is not logged in and the
    # request path is not in the list of allowed anonymous paths
    if not context.get('user') and toolkit.request.path not in allowed_anon_paths:
        return {'success': False}

    return {'success': True}

class Disable_Anon_AccessPlugin(plugins.SingletonPlugin):
    plugins.implements(plugins.IAuthFunctions)

    def get_auth_functions(self):
        return {'site_read': site_read}

Он запрещает анонимным пользователям доступ к любым страницам (кроме связанных с входом в систему), но обеспечивает ошибку 403 Forbidden на всех страницах до входа в систему.

(также запросы API не выполняются с ошибкой 500, если вы не вошли в систему или не предоставили ключ API, но я могу жить с этим)

Я не могу найти способ перенаправления на страницу входа в систему, если он не вошел в систему и / или не работает функция "запомнить меня".

Добавление что-то вроде: toolkit.redirect_to ('/ user / login') вместо return {'success': False} не дает эффекта.

Я также изучил интерфейс IRoutes, но не могу понять, как получить текущего зарегистрированного пользователя (или проверить, вошел ли пользователь в систему)

Ответы [ 2 ]

0 голосов
/ 26 июля 2019

Я видел следующий подход, используемый в CKAN для предотвращения незарегистрированного доступа к сайту.

Используется интерфейс плагина IMiddleware:

class AuthMiddleware(object):
    def __init__(self, app, app_conf):
        self.app = app
    def __call__(self, environ, start_response):
        # if logged in via browser cookies or API key, all pages accessible
        if 'repoze.who.identity' in environ or self._get_user_for_apikey(environ) or not is_iar():
            return self.app(environ,start_response)
        else:
            # otherwise only login/reset and front pages are accessible
            if (environ['PATH_INFO'] == '/' or environ['PATH_INFO'] == '/user/login' or environ['PATH_INFO'] == '/user/_logout'
                                or '/user/reset' in environ['PATH_INFO'] or environ['PATH_INFO'] == '/user/logged_out'
                                or environ['PATH_INFO'] == '/user/logged_in' or environ['PATH_INFO'] == '/user/logged_out_redirect'):
                return self.app(environ,start_response)
            else:
                # http://rufuspollock.org/2006/09/28/wsgi-middleware/
                environ['wsgiorg.routing_args'] = '',{'action': 'login', 'controller': 'user'}
                return self.app(environ,start_response)

    def _get_user_for_apikey(self, environ):
        # Adapted from https://github.com/ckan/ckan/blob/625b51cdb0f1697add59c7e3faf723a48c8e04fd/ckan/lib/base.py#L396
        apikey_header_name = config.get(base.APIKEY_HEADER_NAME_KEY,
                                        base.APIKEY_HEADER_NAME_DEFAULT)
        apikey = environ.get(apikey_header_name, '')
        if not apikey:
            # For misunderstanding old documentation (now fixed).
            apikey = environ.get('HTTP_AUTHORIZATION', '')
        if not apikey:
            apikey = environ.get('Authorization', '')
            # Forget HTTP Auth credentials (they have spaces).
            if ' ' in apikey:
                apikey = ''
        if not apikey:
            return None
        apikey = unicode(apikey)
        # check if API key is valid by comparing against keys of registered users
        query = model.Session.query(model.User)
        user = query.filter_by(apikey=apikey).first()
        return user

, которыйзатем добавлен в ваш класс плагинов, например

class Disable_Anon_AccessPlugin(plugins.SingletonPlugin):
    plugins.implements(plugins.IMiddleware, inherit=True)

    def make_middleware(self, app, config):
        return AuthMiddleware(app, config)
0 голосов
/ 03 июля 2019

Я думаю, что есть несколько способов достичь этого.

Наверное, самый простой. Вы можете попробовать что-то вроде предложения, чтобы проверить, вошел ли пользователь на каждой странице, и перенаправить, если нет. Но это позволяет людям узнать, что сайт существует, и попытаться войти в систему.

Вы можете отключить некоторую аутентификацию и поместить ее на шлюз / балансировщик нагрузки / обратный прокси-сервер перед приложением и выполнить аутентификацию там (я видел похожее - azure со шлюзом приложения, на котором запущен nginx с azure AD).

Если вы используете LDAP, я предполагаю, что у вас может быть локальная сеть (возможно, интрасеть?). Вы можете просто установить это за этим. Или создайте брандмауэр, который блокирует доступ, если только определенная сеть или IP не блокируют

Еще одно предложение

...