扭曲的身份验证问题

发布于 2024-11-25 13:11:21 字数 4451 浏览 2 评论 0原文

我在 pb、cred 中有错误...

我们有一个简单的客户端:

#!/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()

如果我们连接 -> view.callRemote("foo", 13) 和 Disconnect

如果我们没有连接 ->打印'错误的登录名或密码'并断开

服务器代码

#!/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'

请帮助我理解问题。

I have error in pb, cred...

We have a simple client:

#!/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()

If we connect -> perspective.callRemote("foo", 13) and Disconnect

If we no connect -> print 'bad login or password' and Disconnect

sever code

#!/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()

The problem is that with this writing displays an error:

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

Why should he IUsernameHashedPassword?
If i change to

 credentialInterfaces = (credentials.IUsernamePassword, redentials.IUsernameHashedPassword)

Code is executed on but died on string:

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'

Please help me understand the problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撩心不撩汉 2024-12-02 13:11:21

您需要使用 twisted.spread.pb .IUsernameMD5Password凭据对象来登录,因为Twisted的PB在身份验证过程中使用了一点质询/响应方案,这需要密码散列 (MD5)。该算法目前硬编码在PB模块中。您无法轻松地通过 PB 实现/使用其他凭证容器,除非您计划推出自己的身份验证子协议。

该协议旨在保护客户端和服务器免受中间人攻击。

我建议查看 InMemoryUsernamePasswordDatabaseDontUse 了解检查器如何检查传递给他们的凭据(该类的名称是一个微妙的提示)不要在生产服务器中使用该类...)

You need to use a twisted.spread.pb.IUsernameMD5Password credentials object to log in, because Twisted's PB uses a little challenge/response scheme during authentication, which requires the password to be hashed (MD5). This algorithm is currently hard-coded in the PB module. You cannot easily implement/use other credential containers with PB, unless you are planning to roll your own authentication sub-protocol.

This protocol is intended to protect client and server against man-in-the-middle attacs.

I would recommend having a look at the source code of InMemoryUsernamePasswordDatabaseDontUse for a description of how checkers are supposed to check the credentials handed to them (the name of that class is a subtle hint not to use the class in a production server...)

陈年往事 2024-12-02 13:11:21

我的简单测试服务器使用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()

My simple test server use PB and 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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文