Pyramid 中的多重身份验证策略

Multiple Authhentication Policies in Pyramid

我已收到添加HTTP认证的任务(BasicAuthAuthenticationPolicy) to a Pyramid application that already have a AuthTktAuthenticationPolicy已完成...

基本上我需要创建一个 RESTful API 来验证用户(我可以使用 BasicAuthAuthenticationPolicy 吗?)。

有没有办法检查用户是否正在使用 Web 界面,或使用 api - 检查要使用的身份验证策略?

我还没有遇到过在单个 Pyramid 应用程序中涵盖两种不同身份验证策略的文档(如果可能的话)。

PS:
我遇到了一个博客系列,该系列开始展示如何使用金字塔框架创建 RESTful API...Blogger 报告说系列中将有 6 篇文章,但我只成功了找到其中两篇文章:Building a RESTful API with Pyramid - Setup and Building a RESTful API with Pyramid - Resource and Traversal。我 am/was 期待他的最后一篇文章:使用金字塔构建 RESTful API - 身份验证和 ACL,但他似乎不会完成这个系列。

回顾一下我的问题:

  1. 我可以使用 BasicAuthAuthenticationPolicy 构建 RESTful api 来验证用户吗?
  2. 有没有办法检查用户是否正在使用 Web 界面,或者使用 API - 检查要使用的身份验证策略?

如有任何帮助,我们将不胜感激。

Pyramid 不会让应用程序的不同部分使用不同的策略变得容易(也许可以使用自定义装饰器来解决)但是对于多个策略,请查看 pyramid_authstack。我将它与 Session 和 BasicAuth 策略一起使用,目的与您相同。

如果使用一个金字塔应用程序和两个身份验证策略并不简单,您可以将两个具有不同策略的独立金字塔应用程序组装到一个 WSGI 堆栈中。每个应用程序都可以导入相同的 Python 代码,因此,从本质上讲,这将是两个使用相同视图和所有内容的启动文件。

如果您的应用程序有不同的 URL,您可以为此使用 paste.urlmap,如果您的要求更复杂,您甚至可以编写自己的路由器(例如,具有特定 HTTP header 的请求是路由到一个应用程序而没有路由到另一个应用程序)

所以我所做的是合并金字塔 BasicAuthAuthenticationPolicyCallbackAuthenticationPolicy,最后得到 this

我修改了 callback 方法以使用 redis 会话

要使用此 class(HTTPThentication),您可以执行以下操作(这是我如何为我的用例实现它的示例):

def _get_userid(details, request):
    userre = re.compile("""^([a-zA-Z1-9\.]+):([a-zA-Z1-9\.:-]+)$""", re.I)
    userpass = base64.b64decode(details[1])
    res = userre.search(userpass)
    if res:
        return res.group()[0]

def authcheck(username, password, request):
    user = Users.by_username(username, enabled=True)
    host = request.registry.settings.get("authentication.host", "127.0.0.1")
    maxattempts = request.registry.settings.get("authentication.maxattempts",5)
    base = _get_userid(request.authorization, request)
    if request.redis.exists("pimssess:%s" % base64.b64encode(request.remote_addr+":"+base)):
        store = pickle.loads(request.redis.get("pimssess:%s" % base64.b64encode(request.remote_addr+":"+base)))
        if store.get("auth.attempts").get(request.remote_addr):
            if store["auth.attempts"][request.remote_addr] >= maxattempts:
                raise HTTPMethodNotAllowed(body="You have been locked out for 5 minutes")

    if user and user.agent and not user.is_http_auth:
        raise HTTPMethodNotAllowed(body="You are not permitted http access")
    if user and user.agent and user.host != host:
        raise HTTPMethodNotAllowed(body="Your host is not permitted http access")
    if user and user.agent and not user.validate_password(password):
        time.sleep(1.5)
        raise HTTPForbidden(body="Failed login, Incorrect password")
    return getGroups(username)

getGroups 函数返回附加到用户的 groups 列表,即 ['admin', 'reporting']

我遵循了这个例子:BasicAuthAuthenticationPolicy(滚动到底部)

对于 Web 界面登录(CallbackAuthentication),您创建一个登录界面,并创建视图以容纳模板(检查密码和用户名匹配等)

哦我差点忘了...在你的项目__init__.py,当你调用AuthPolicy,在def main(...)。我做到了:

authentication = AuthPolicy(secret='@#^&*$!DSYUIDSA8321789DS',
                        hashalg='sha512', check=authcheck, debug=True)
authorization = ACLAuthorizationPolicy()

config = Configurator(settings=settings, root_factory=RootFactory,
                  authentication_policy=authentication,
                  authorization_policy=authorization)

我希望这可以帮助别人。