0

repoze.who通过删除所有base_config.sa_auth...和禁用默认配置后base_config.auth_backendconfig/app_.cfg.py应该可以将 repoze.who 配置为config/middleware.py.

所以我创建了一个config/auth.py这样的文件:

from logging import getLogger

from repoze.who.middleware import PluggableAuthenticationMiddleware
from repoze.who.classifiers import default_challenge_decider, default_request_classifier

from repoze.who.plugins.basicauth import BasicAuthPlugin
from repoze.who.plugins.htpasswd import HTPasswdPlugin, plain_check

def add_auth(app):
    htpasswd = HTPasswdPlugin('/.../htpasswd', plain_check)
    authenticators = [('htpasswd', htpasswd)]

    base_auth = BasicAuthPlugin('Inventory DB')
    challengers = [('base_auth', base_auth)]
    identifiers = [('base_auth', base_auth)]

    mdproviders = []

    log_stream = getLogger('auth')

    app_with_mw = PluggableAuthenticationMiddleware(
        app,
        identifiers,
        authenticators,
        challengers,
        mdproviders,
        default_request_classifier,
        default_challenge_decider,
        log_stream,
        )
    return app_with_mw

其中纯文本密码仅用于测试。然后,在config/middleware.py这个函数中被导入并应用到函数app的最后一步make_app

from invdb.config.app_cfg import base_config
from invdb.config.environment import load_environment
from auth import add_auth

__all__ = ['make_app']
make_base_app = base_config.setup_tg_wsgi_app(load_environment)
def make_app(global_conf, full_stack=True, **app_conf):
    app = make_base_app(global_conf, full_stack=True, **app_conf)
    app = add_auth(app)
    return app

现在的问题是,身份验证实际上不起作用。不需要任何身份验证的控制器不会质询。控制器allow_only = tg.predicate.not_anonymous将挑战 http 身份验证。但是即使plain_check 返回True登录名也会立即被遗忘,并且再次显示挑战。tg.request.identity停留None

我究竟做错了什么?

4

2 回答 2

2

有一个更简单的解决方案是用自定义中间件替换整个身份验证堆栈。如身份验证文档所述,您可以自己配置身份验证堆栈app_cfg.py

例如,如果您想强制使用基本身份验证,您只需设置challengers,identifiers然后authenticators返回数据以tg.request.identity使用authmetadata

这是基本身份验证的示例 app_cfg(请记住删除任何其他basic_config.sa_auth 条目,否则它可能会因意外参数而崩溃):

# Name our custom auth backend, if this is None TG will
# disable the whole authentication stack.
base_config.auth_backend = 'htpasswd'

from tg.configuration.auth import TGAuthMetadata

#This tells to TurboGears how to retrieve the data for your user
class ApplicationAuthMetadata(TGAuthMetadata):
    def __init__(self, sa_auth):
        self.sa_auth = sa_auth

    def get_user(self, identity, userid):
        # As we use htpasswd for authentication
        # we cannot lookup the user in a database,
        # so just return a fake user object
        from tg.util import Bunch
        return Bunch(display_name=userid, user_name=userid)

    def get_groups(self, identity, userid):
        # If the user is manager we give him the
        # managers group, otherwise no groups
        if userid == 'manager':
            return ['managers']
        else:
            return []

    def get_permissions(self, identity, userid):
        return []

base_config.sa_auth.authmetadata = ApplicationAuthMetadata(base_config.sa_auth)

from repoze.who.plugins.basicauth import BasicAuthPlugin
from repoze.who.plugins.htpasswd import HTPasswdPlugin, plain_check

# Use htpasswd for checking user credentials, remember to write the password in clear
# text as we are using the plain_check function to check them.
base_config.sa_auth.authenticators = [('htpasswd', HTPasswdPlugin('./passwd_file', plain_check))]

# Use BasicAuth plugin to ask user for credentials, this will replace
# the whole login form and cookie based authentication
base_auth = BasicAuthPlugin('MyTGApp')
base_config.sa_auth.challengers = [('basicauth', base_auth)]
base_config.sa_auth.identifiers = [('basicauth', base_auth)]

# Disable the login form, it won't work anyway as the credentials
# for basic auth must be provided through the browser itself
base_config.sa_auth.form_identifies = False
于 2014-05-26T20:17:24.583 回答
0

amol 的答案很可能是你应该怎么做。无论如何,这是我在此期间找到的解决方案:不要使用内置的predicate.not_anonymous. 这似乎依赖于部分repoze.what或未AuthMetaData配置的部分。所以我发明了自己的谓词:

class identified_user(predicates.Predicate):
    def evaluate(self, environ, credentials):
        if environ.get('repoze.who.identity') is None:
            self.unmet()
于 2014-05-26T20:36:20.177 回答