我在pb中有错误,信用卡......
我们有一个简单的客户:
#!/usr/bin/env python
from twisted.spread import pb
from twisted.internet import reactor
from twisted.cred import credentials
def main():
factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8801, factory)
def1 = factory.login(credentials.UsernamePassword("admin", "pass2"))
def1.addCallback(connected)
def1.addErrback(bad_connected)
def1.addBoth(disconnect)
reactor.run()
def bad_connected(perspective):
print 'bad login or password', perspective
perspective.addCallback(disconnect)
def connected(perspective):
print "got perspective1 ref:", perspective
print "asking it to foo(13)"
return perspective.callRemote("foo", 13)
def disconnect(perspective):
print 'disconnect'
reactor.stop()
main()
如果我们连接 - > perspective.callRemote(“foo”,13)和Disconnect
如果我们没有连接 - >打印'bad login or password'并断开连接
服务器代码
#!/usr/bin/env python
from zope.interface import implements
from twisted.python import failure, log
from twisted.cred import portal, checkers, credentials, error as credError
from twisted.internet import defer, reactor
from twisted.spread import pb
class PasswordDictChecker:
implements(checkers.ICredentialsChecker)
credentialInterfaces = (credentials.IUsernamePassword,)
def __init__(self, passwords):
"passwords: a dict-like object mapping usernames to passwords"
self.passwords = passwords
def requestAvatarId(self, credentials):
username = credentials.username
if self.passwords.has_key(username):
if credentials.password == self.passwords[username]:
return defer.succeed(username)
else:
return defer.fail(
credError.UnauthorizedLogin("Bad password"))
else:
return defer.fail(
credError.UnauthorizedLogin("No such user"))
class MyRealm(object):
implements(portal.IRealm)
def requestAvatar(self, user, mind, *interfaces):
assert pb.IPerspective in interfaces
avatar = MyAvatar(user)
avatar.attached(mind)
return pb.IPerspective, avatar, lambda a=avatar:a.detached(mind)
class MyAvatar(pb.Avatar):
def __init__(self, user):
self.user = user
def attached(self, mind):
self.remote = mind
print 'User %s connected' % (self.user,)
def detached(self, mind):
self.remote = None
print 'User %s disconnected' % (self.user,)
passwords = {
'admin': 'aaa',
'user1': 'bbb',
'user2': 'ccc'
}
if __name__ == "__main__":
checker = PasswordDictChecker(passwords)
realm = MyRealm()
p = portal.Portal(realm, [checker])
reactor.listenTCP(8801, pb.PBServerFactory(p))
reactor.run()
问题在于,写入时会显示错误:
Unhandled Error
Traceback (most recent call last):
Failure: twisted.cred.error.UnhandledCredentials: No checker for twisted.cred.credentials.IUsernameHashedPassword, twisted.spread.pb.IUsernameMD5Password, twisted.spread.interfaces.IJellyable
他为什么要IUsernameHashedPassword? 如果我改为
credentialInterfaces = (credentials.IUsernamePassword, redentials.IUsernameHashedPassword)
代码执行但在字符串上死亡:
if credentials.password == self.passwords[username]:
Unhandled Error
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\twisted\spread\pb.py", line 841, in _recvMessage
netResult = object.remoteMessageReceived(self, message, netArgs, netKw)
File "C:\Python27\lib\site-packages\twisted\spread\flavors.py", line 114, in remoteMessageReceived
state = method(*args, **kw)
File "C:\Python27\lib\site-packages\twisted\spread\pb.py", line 1347, in remote_respond
d = self.portal.login(self, mind, IPerspective)
File "C:\Python27\lib\site-packages\twisted\cred\portal.py", line 115, in login
return maybeDeferred(self.checkers[i].requestAvatarId, credentials
--- <exception caught here> ---
File "C:\Python27\lib\site-packages\twisted\internet\defer.py", line 133, in maybeDeferred
result = f(*args, **kw)
File "C:/Dropbox/my_py/network/pb-cred/pb6serverV2.py", line 21, in requestAvatarId
if credentials.password == self.passwords[username]:
exceptions.AttributeError: _PortalAuthChallenger instance has no attribute 'password'
请帮我理解这个问题。
答案 0 :(得分:2)
您需要使用twisted.spread.pb.IUsernameMD5Password
凭据对象登录,因为Twisted的PB在身份验证期间使用了一些挑战/响应方案,这需要对密码进行哈希处理(MD5)。该算法目前在PB模块中进行了硬编码。您不能轻易地使用PB实现/使用其他凭据容器,除非您计划推出自己的身份验证子协议。
此协议旨在保护客户端和服务器免受中间人的影响。
我建议您查看InMemoryUsernamePasswordDatabaseDontUse
的源代码,了解如何检查棋子应该检查传递给他们的凭据(该类的名称是一个微妙的提示,不使用该类中的生产服务器...)
答案 1 :(得分:0)
我的简单测试服务器使用PB和MySQL
# -*- coding: utf-8 -*-
import MySQLdb
from twisted.cred import portal, checkers, credentials, error as credError
from twisted.protocols import basic
from twisted.internet import protocol, reactor, defer
from zope.interface import Interface, implements
from twisted.spread import pb
from twisted.enterprise import adbapi, util as dbutil
class MyPerspective(pb.Avatar):
def __init__(self, name):
self.name = name
def perspective_foo(self, arg):
print "I am", self.name, "perspective_foo(",arg,") called on", self
return arg
class MyRealm:
implements(portal.IRealm)
def requestAvatar(self, avatarId, mind, *interfaces):
#print 'qqqq', avatarId
if pb.IPerspective not in interfaces:
raise NotImplementedError
return pb.IPerspective, MyPerspective(avatarId), lambda:None
class DbPasswordChecker(object):
implements(checkers.ICredentialsChecker)
credentialInterfaces = (credentials.IUsernamePassword,
credentials.IUsernameHashedPassword)
def __init__(self, dbconn):
self.dbconn = dbconn
def requestAvatarId(self, credentials):
query = "select userid, password from user where username = %s" % (
dbutil.quote(credentials.username, "char"))
return self.dbconn.runQuery(query).addCallback(
self._gotQueryResults, credentials)
def _gotQueryResults(self, rows, userCredentials):
if rows:
userid, password = rows[0]
return defer.maybeDeferred(
userCredentials.checkPassword, password).addCallback(
self._checkedPassword, userid)
else:
raise credError.UnauthorizedLogin, "No such user"
def _checkedPassword(self, matched, userid):
if matched:
return userid
else:
raise credError.UnauthorizedLogin("Bad password")
DB_DRIVER = "MySQLdb"
DB_ARGS = {
'db': 'dbname',
'user': 'root',
'passwd': '',
}
connection = adbapi.ConnectionPool(DB_DRIVER, **DB_ARGS)
p = portal.Portal(MyRealm())
p.registerChecker(DbPasswordChecker(connection))
#p.registerChecker(PasswordDictChecker(passwords))
reactor.listenTCP(8800, pb.PBServerFactory(p))
reactor.run()