Найти - Пользователи
Полная версия: twisted авторизация cread, pb
Начало » Network » twisted авторизация cread, pb
1
necrozyablo
Изучаю Твистед, давно не чувствовал себя таким беспомощным…

Имеем простой клиент:
#!/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()
Конектимся с логином паролем, если ловим ошибку то говорим print ‘bad login or password’
Если логин пароль подошли то asking it to foo(13) и опять таки дисконект.

Собственно все проблемы в данный момент в сервере, он рвёт мой мозг уже несколько дней и я не могу понять в чём проблема.
Вот его код:
#!/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()
Собственно проблема в том что если credentialInterfaces = (credentials.IUsernamePassword,)
то сразу улетаем ошибку:
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, credentials.IUsernameHashedPassword)
После этого авторизация проходит дальше и доходит до строки
if credentials.password == self.passwords:
И умирает с:
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'
Пожалуйста помогите разобраться в чём проблема.
necrozyablo
На Stackoverflow пишут что
You need to use a twisted.spread.pb.IUsernameMD5Password credentials object to log in. 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 to use with PB, unless you are planning to roll your own authentication sub-protocol.
necrozyablo
Вопрос, стандартно всюду в примерах про PB используются
p.registerChecker(checkers.InMemoryUsernamePasswordDatabaseDontUse(admin='aaa', guest='bbb'))
Может кто нибудь показать другую реализацию? Скажем через MySQLdb.
Я вот хоть убейся не могу понять как переписать код чтобы не использовать InMemoryUsernamePasswordDatabaseDontUse и использовать при этом PB


—————
UPDATE
————–
Наваял вот такой код:
# -*- 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()
Вроде работает и делает что я хотел. Хотя не понятно правильно ли я делаю с идологической точки зрения…
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB