【问题标题】:Basic HTTP authentication with twisted not working扭曲的基本 HTTP 身份验证不起作用
【发布时间】:2018-10-02 21:56:54
【问题描述】:

我有以下代码:

import sys

from zope.interface import implementer

from twisted.python import log
from twisted.internet import reactor
from twisted.web import server, resource, guard
from twisted.cred.portal import IRealm, Portal
from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse


class GuardedResource(resource.Resource):
    """
    A resource which is protected by guard and requires authentication in order
    to access.
    """
    def getChild(self, path, request):
        return self


    def render(self, request):
        return "Authorized!"



@implementer(IRealm)
class SimpleRealm(object):
    """
    A realm which gives out L{GuardedResource} instances for authenticated
    users.
    """

    def requestAvatar(self, avatarId, mind, *interfaces):
        if resource.IResource in interfaces:
            return resource.IResource, GuardedResource(), lambda: None
        raise NotImplementedError()

def main():
    log.startLogging(sys.stdout)
    checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe='blow')]
    portal = Portal(SimpleRealm(), checkers)

    resource = guard.HTTPAuthSessionWrapper(portal, [guard.BasicCredentialFactory('auth')])

    reactor.listenTCP(8889, server.Site(resource = resource))
    reactor.run()

if __name__ == '__main__':
    main()

当我们启动服务器并访问 url 时: http://localhost:8889/ 会弹出一个提示,要求我们输入用户名和密码。输入user = joepassword = blow 后,我们仍然无权访问该网站。上面的代码有什么问题以及如何解决?

【问题讨论】:

  • 我无法重现您的行为。 curl --verbose http://localhost:8889/ 收到 401 响应。 curl --verbose http://joe:blow@localhost:8889/ 收到 200 响应。
  • 奇怪!我在Ubuntu 18.04 LTStwisted 18.7.0 上运行Python 3.6.5 并尝试curl --verbose http://joe:blow@localhost:8889/。但是我收到了这个回复:< HTTP/1.1 401 Unauthorized < Server: TwistedWeb/18.7.0 < Date: Wed, 03 Oct 2018 20:29:49 GMT * Authentication problem. Ignoring this. < WWW-Authenticate: basic realm="auth" < Content-Length: 12 < Content-Type: text/html
  • 我在 Python 2.7 上测试过。在 Python 3.6.5 上重复测试,我观察到与您相同的行为。看起来有人未能正确地将一些 Twisted Web 移植到 Python 3。您可能应该在 Twisted 跟踪器中提交一张票。
  • 感谢让-保罗!能否请您提供 Twisted 跟踪器的链接?

标签: twisted twisted.web


【解决方案1】:

所以我按照@Jean-Paul Calderone 的建议在 trac 上发布并解决了问题here

有两件事需要解决

  1. render 方法在 python3 中返回字节
    def render(self, request):
        return "Authorized!".encode('utf8')
  1. InMemoryUsernamePasswordDatabaseDontUse 中的密码必须以字节为单位
    checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe=b'blow')]

所以为了让您的代码在 py2 和 py3 中运行,请使用这个

from __future__ import print_function
import sys
from zope.interface import implementer
from twisted.python import log
from twisted.internet import reactor
from twisted.web import server, resource, guard
from twisted.cred.portal import IRealm, Portal
from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse


class GuardedResource(resource.Resource):
    """
    A resource which is protected by guard and requires authentication in order
    to access.
    """
    def getChild(self, path, request):
        return self


    def render(self, request):
        return "Authorized!".encode('utf8')


@implementer(IRealm)
class SimpleRealm(object):
    """
    A realm which gives out L{GuardedResource} instances for authenticated
    users.
    """

    def requestAvatar(self, avatarId, mind, *interfaces):
        if resource.IResource in interfaces:
            return resource.IResource, GuardedResource(), lambda: None
        raise NotImplementedError()

def main():
    log.startLogging(sys.stdout)
    checkers = [InMemoryUsernamePasswordDatabaseDontUse(joe=b'blow')]
    portal = Portal(SimpleRealm(), checkers)

    resource = guard.HTTPAuthSessionWrapper(portal, [guard.BasicCredentialFactory('auth')])

    reactor.listenTCP(8889, server.Site(resource = resource))
    reactor.run()

if __name__ == '__main__':
    main()

【讨论】:

    猜你喜欢
    • 2014-01-22
    • 2014-12-31
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 2014-09-06
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多