twisted的cred

最近在看《Twisted Network Programming Essentials 2nd》一书,网上找不到中文版的(好像第一版被翻译了部分,第二版好像没被翻译),哭瞎。里面有讲cred的。

各个重要的参数说明一下:http://twistedmatrix.com/documents/13.1.0/core/howto/cred.html#auto2这里有很详细说明哦。

Credentials:与验证用户的信息有关。最常用的就是记录着用户名和密码。(我喜欢把它叫做一个装有你的用户名密码的容器。)实现了twisted.cred.credentials.ICredentials

Avatar:你验证成功后的代表着用户的一个对象。

AvatarID:这个用来表明用户的身份的。在本例子里,就是user

Credentials checker:这个是用验证你的Credentials是否合法。如果合法的话,会返回一个avatarID。例子中的InMemoryUsernamePasswordDatabaseDontUse()这是一个CredentialsChecker

Realm:为所有用户定义一些操作。在Realm的requestAvatar方法中,会传入一个avatarId,可以根据不同的用户来规定不同的权限。它会返回一个avatar对象

Portal:把一系列的CredentialsChecker集中起来。主要完成的就是把Credentials与Credentials checker间的信息进行核对。portal的login方法,会返回一个Deferred,注册回调checker的requestAvatarId,这会返回一个AvatarID,然后再注册回调一个Realm的requestAvatar。

 

下面代码,实现了一个需要用户凭证的echo服务器,使用user pass 来验证身份。

 

#!/usr/bin/env python
#coding:utf8
# Author          : tuxpy
# Email           : q8886888@qq.com
# Last modified   : 2014-08-25 15:35:35
# Filename        : tw_cred.py
# Description     : 
from zope.interface import implements,Interface
from twisted.cred import checkers,credentials,portal
from twisted.internet import protocol,reactor
 
from twisted.protocols import basic
 
class IProtocolAvatar(Interface):
    def logout():
        """
        clean up per-login resources ollocated to this avator.
        """
 
class EchoAvatar(object):
    implements(IProtocolAvatar)
 
    def logout(self):
        pass
 
class Echo(basic.LineReceiver):
    protal=None
    avatar=None
    logout=None
    delimiter='\n'
 
    def cocnnectionLost(self,reason):
        if self.logout:
            self.logout()
            self.avater=None
            seslf.logout=None
 
    def lineReceived(self,line):
        if not self.avatar:
            username,password=line.strip().split(" ")
            self.tryLogin(username,password)
        else:
            self.sendLine(line)
 
    def tryLogin(self,username,password):
        self.portal.login(credentials.UsernamePassword(username,
            password),
            None,IProtocolAvatar).addCallbacks(self._cbLogin,
                    self._ebLogin)
 
    def _cbLogin(self,(interface,avatar,logout)):
        self.avatar=avatar
        self.logout=logout
        self.sendLine("Login successful,please procees.")
 
    def _ebLogin(self,failure):
        self.sendLine("Login denied,goodbye.")
        self.transport.loseConnection()
 
class EchoFactory(protocol.Factory):
    def __init__(self,portal):
        self.portal=portal
 
    def buildProtocol(self,addr):
        protocol=Echo()
        protocol.portal=self.portal
        return protocol
        
 
class Realm(object):
    implements(portal.IRealm)
    
    def requestAvatar(self,avatarId,mind,*interfaces):
        for iface in interfaces:
            if iface is IProtocolAvatar:
                avatar=EchoAvatar()
                return IProtocolAvatar,avatar,avatar.logout
 
        raise NotImplementedError("This realm only supports the IProtocolAvatar interface.")
 
realm=Realm()
myPortal=portal.Portal(realm)
checker=checkers.InMemoryUsernamePasswordDatabaseDontUse()
checker.addUser("user","pass")
myPortal.registerChecker(checker)
reactor.listenTCP(1234,EchoFactory(myPortal))
reactor.run()


 

下面这图,很说明问题,看懂了,就基本上明白这几个

点击查看原图

 

1.先是调用portal.login方法,将Credentials(UsernamePassword),mind(通常是None),interfaces(IProtocolAvatar) 当作为参数传入。

2.把Credentials与portal中已经注册了的checker(Credentials Checkers,使用portal的rergisterChecker(checker)注册)进行信息的匹配。

3.匹配无误,就会返回一个avatarId.

4.avatarId返回,激活回调函数self.realm.requestAvatar。

5.返回符合条件的avatar

6.返回avatar和logout方法

 

这还有一张twisted how to 上的图:

点击查看原图


一些源码:

class Portal:

    """

    A mediator between clients and a realm.

 

    A portal is associated with one Realm and zero or more credentials checkers.

    When a login is attempted, the portal finds the appropriate credentials

    checker for the credentials given, invokes it, and if the credentials are

    valid, retrieves the appropriate avatar from the Realm.

 

    This class is not intended to be subclassed.  Customization should be done

    in the realm object and in the credentials checker objects.

    """

    def __init__(self, realm, checkers=()):

        """

        Create a Portal to a L{IRealm}.

        """

        self.realm = realm

        self.checkers = {}

        for checker in checkers:

            self.registerChecker(checker)

 

    def listCredentialsInterfaces(self):

        """

        Return list of credentials interfaces that can be used to login.

        """

        return self.checkers.keys()

 

    def registerChecker(self, checker, *credentialInterfaces):

        if not credentialInterfaces:

            credentialInterfaces = checker.credentialInterfaces

        for credentialInterface in credentialInterfaces:

            self.checkers[credentialInterface] = checker

 

    def login(self, credentials, mind, *interfaces):

        """

        @param credentials: an implementor of

            L{twisted.cred.credentials.ICredentials}

 

        @param mind: an object which implements a client-side interface for

            your particular realm.  In many cases, this may be None, so if the

            word 'mind' confuses you, just ignore it.

 

        @param interfaces: list of interfaces for the perspective that the mind

            wishes to attach to. Usually, this will be only one interface, for

            example IMailAccount. For highly dynamic protocols, however, this

            may be a list like (IMailAccount, IUserChooser, IServiceInfo).  To

            expand: if we are speaking to the system over IMAP, any information

            that will be relayed to the user MUST be returned as an

            IMailAccount implementor; IMAP clients would not be able to

            understand anything else. Any information about unusual status

            would have to be relayed as a single mail message in an

            otherwise-empty mailbox. However, in a web-based mail system, or a

            PB-based client, the ``mind'' object inside the web server

            (implemented with a dynamic page-viewing mechanism such as a

            Twisted Web Resource) or on the user's client program may be

            intelligent enough to respond to several ``server''-side

            interfaces.

 

        @return : A deferred which will fire a tuple of (interface,

            avatarAspect, logout).  The interface will be one of the interfaces

            passed in the 'interfaces' argument.  The 'avatarAspect' will

            implement that interface. The 'logout' object is a callable which

            will detach the mind from the avatar. It must be called when the

            user has conceptually disconnected from the service. Although in

            some cases this will not be in connectionLost (such as in a

            web-based session), it will always be at the end of a user's

            interactive session.

        """

        for i in self.checkers:

            if i.providedBy(credentials):

                return maybeDeferred(self.checkers[i].requestAvatarId, credentials

                    ).addCallback(self.realm.requestAvatar, mind, *interfaces

                    )

        ifac = providedBy(credentials)

        return defer.fail(failure.Failure(error.UnhandledCredentials(

            "No checker for %s" % ', '.join(map(reflect.qual, ifac)))))





class InMemoryUsernamePasswordDatabaseDontUse:

    """

    An extremely simple credentials checker.


    This is only of use in one-off test programs or examples which don't

    want to focus too much on how credentials are verified.


    You really don't want to use this for anything else.  It is, at best, a

    toy.  If you need a simple credentials checker for a real application,

    see L{FilePasswordDB}.

    """


    implements(ICredentialsChecker)


    credentialInterfaces = (credentials.IUsernamePassword,

                            credentials.IUsernameHashedPassword)


    def __init__(self, **users):

        self.users = users


    def addUser(self, username, password):

        self.users[username] = password


    def _cbPasswordMatch(self, matched, username):

        if matched:

            return username

        else:

            return failure.Failure(error.UnauthorizedLogin())


    def requestAvatarId(self, credentials):

        if credentials.username in self.users:

            return defer.maybeDeferred(

                credentials.checkPassword,

                self.users[credentials.username]).addCallback(

                self._cbPasswordMatch, str(credentials.username))

        else:

            return defer.fail(error.UnauthorizedLogin())


转载于:https://my.oschina.net/tuxpy/blog/306731

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值