在使用Twisted的Perspective Broker创建一个网络应用程序时,遇到一个问题:它自动使用MD5质询-响应方案进行身份验证。由于存在许多安全漏洞,最好不要在服务器端存储MD5哈希值。scrypt、bcrypt或pbkdf2等算法提供了更安全的替代方法。
尽管这些算法在Python中很容易获得,但目前还不清楚是否可以使用Perspective Broker实现自定义身份验证方案。从源代码来看,MD5似乎与系统紧密集成。
2. 解决方案
为了Perspective Broker实现自定义身份验证方案,只需要在一个根对象上实现一组方法调用,这些调用完成后即可访问所需的应用程序级对象。
无法重新使用PB内置的登录方法及其附带的线协议消息,但这没关系;这正是打算替换的东西。
注意,在构造一个PBServerFactory时,提供了一个根对象。如果想调用该对象上的方法,而不是执行“标准”的PB登录并在返回的化身(即,每个用户/每个连接对象)上调用方法,则需在PB客户端工厂上调用getRootObject,并在结果上使用callRemote。
以下是代码示例:
from twisted.cred import portal
from twisted.internet import protocol
class MyRealm:
def requestAvatar(self, avatarId, mind):
return MyAvatar(), None
class MyAvatar:
def remote_doSomething(self, arg):
# Do something with arg
class MyProtocol(protocol.Protocol):
def connectionMade(self):
self.factory.getRootObject().then(
lambda root: root.callRemote('login', 'username', 'password')
).addCallbacks(
self._onLoginSuccess,
self._onLoginFailure
)
def _onLoginSuccess(self, result):
# The login was successful; the result contains an avatar object
avatar = result
# Now we can call methods on the avatar, such as:
avatar.callRemote('doSomething', 'Hello, world!')
def _onLoginFailure(self, failure):
# The login failed; handle the failure appropriately
print(failure)
class MyFactory(protocol.Factory):
def buildProtocol(self, addr):
return MyProtocol()
portal = portal.Portal(MyRealm())
from twisted.internet import reactor
reactor.listenTCP(8000, MyFactory())
reactor.run()
在上面的示例中,MyRealm类充当身份验证领域,它定义了requestAvatar方法,该方法将返回一个MyAvatar对象和None。MyAvatar类是应用程序级别对象的表示,它定义了用作远程方法的remote_doSomething方法。
MyProtocol类是网络协议,它处理与客户端的连接。在connectionMade方法中,它首先获取根对象,然后调用login方法。login方法接受用户名和密码作为参数,如果成功,它将返回一个MyAvatar对象,否则返回一个错误。
如果登录成功,则调用_onLoginSuccess方法,其中调用doSomething方法在MyAvatar对象上执行远程操作。如果登录失败,则调用_onLoginFailure方法,其中处理错误。
最后,MyFactory类是一个协议工厂,它构建MyProtocol实例。然后,在reactor.listenTCP行中,将MyFactory实例绑定到端口8000,这将导致侦听传入连接并为每个连接构建MyProtocol实例。
reactor.run()行启动Twisted反应器,它将监听传入连接并调用适当的方法来处理它们。