禁止对CKAN网站进行异常访问的方法

时间:2019-06-25 15:52:09

标签: ckan

我有一个配置了ckanext-ldap扩展名的CKAN站点,但是我只是不认证用户才能访问该站点。

这是我的解决方案,但我并不完全满意:

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禁止错误。

(API请求也会失败,并显示500错误,除非登录或提供API密钥,但我可以接受)

如果没有登录和/或使“记住我”功能正常工作,我无法找到重定向到登录页面的方法。

添加类似以下内容:toolkit.redirect_to('/ user / login')而不是返回{'success':False}无效。

我也查看了IRoutes界面,但无法弄清楚如何获取当前登录用户(或检查用户是否已登录)

2 个答案:

答案 0 :(得分:0)

我认为有几种方法可以实现这一目标。

可能是最简单的。您可以尝试使用类似suggestion to的方法来检查用户是否在每个页面上都已登录,如果没有登录,则进行重定向。但这使人们知道站点在那里并尝试登录。

您可以进行一些身份验证,然后将其放在应用程序前面的网关/负载平衡器/反向代理上并在此处进行身份验证(我看到类似的应用程序网关在运行带有azure AD的nginx的应用程序网关中是azure)。

如果您使用的是LDAP,我猜测您可能具有局域网(可能是内部网?)。您也可以将其设置为该值。或创建阻止访问的防火墙,除非特定的网络或IP阻止。

Another suggestion

答案 1 :(得分:0)

我已经看到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)