python扭曲的信用

时间:2017-03-04 08:59:02

标签: python twisted

我在这里有一个小疑问,因为当我浏览扭曲的例子(写得非常好)时,我看到了使用cred的例子。我不得不提到这种好奇心是因为我越是使用扭曲,我更喜欢它并试图绕着它并详细了解它的功能。现在我的问题是为什么我会首先使用cred?如果它是简单的用户传递凭据,不能像在大多数Web应用程序中那样使用简单的数据库检查?如果它用于制作异步然后无法使用异步版本的db客户端来实现相同的效果?使用relamavatarsportals可以获得什么?我的意思是在哪种情况下可以使用这些东西。我知道这与我对扭曲的信用不足有关,所以请帮忙。下面是前面我说的

from __future__ import print_function

import sys
from zope.interface import implementer, Interface

from twisted.protocols import basic
from twisted.internet import protocol
from twisted.python import log

from twisted.cred import error
from twisted.cred import portal
from twisted.cred import checkers
from twisted.cred import credentials

class IProtocolUser(Interface):
    def getPrivileges():
        """Return a list of privileges this user has."""

    def logout():
        """Cleanup per-login resources allocated to this avatar"""

@implementer(IProtocolUser)
class AnonymousUser:
    def getPrivileges(self):
        return [1, 2, 3]

    def logout(self):
        print("Cleaning up anonymous user resources")

@implementer(IProtocolUser)
class RegularUser:
    def getPrivileges(self):
        return [1, 2, 3, 5, 6]

    def logout(self):
        print("Cleaning up regular user resources")

@implementer(IProtocolUser)
class Administrator:
    def getPrivileges(self):
        return range(50)

    def logout(self):
        print("Cleaning up administrator resources")

class Protocol(basic.LineReceiver):
    user = None
    portal = None
    avatar = None
    logout = None

    def connectionMade(self):
        self.sendLine("Login with USER <name> followed by PASS <password> or ANON")
        self.sendLine("Check privileges with PRIVS")

    def connectionLost(self, reason):
        if self.logout:
            self.logout()
            self.avatar = None
            self.logout = None

    def lineReceived(self, line):
        f = getattr(self, 'cmd_' + line.upper().split()[0])
        if f:
            try:
                f(*line.split()[1:])
            except TypeError:
                self.sendLine("Wrong number of arguments.")
            except:
                self.sendLine("Server error (probably your fault)")

    def cmd_ANON(self):
        if self.portal:
            self.portal.login(credentials.Anonymous(), None, IProtocolUser
                ).addCallbacks(self._cbLogin, self._ebLogin
                )
        else:
            self.sendLine("DENIED")

    def cmd_USER(self, name):
        self.user = name
        self.sendLine("Alright.  Now PASS?")

    def cmd_PASS(self, password):
        if not self.user:
            self.sendLine("USER required before PASS")
        else:
            if self.portal:
                self.portal.login(
                    credentials.UsernamePassword(self.user, password),
                    None,
                    IProtocolUser
                ).addCallbacks(self._cbLogin, self._ebLogin
                )
            else:
                self.sendLine("DENIED")

    def cmd_PRIVS(self):
        self.sendLine("You have the following privileges: ")
        self.sendLine(" ".join(map(str, self.avatar.getPrivileges())))

    def _cbLogin(self, result):
        (interface, avatar, logout) = result
        assert interface is IProtocolUser
        self.avatar = avatar
        self.logout = logout
        self.sendLine("Login successful.  Available commands: PRIVS")

    def _ebLogin(self, failure):
        failure.trap(error.UnauthorizedLogin)
        self.sendLine("Login denied!  Go away.")

class ServerFactory(protocol.ServerFactory):
    protocol = Protocol

    def __init__(self, portal):
        self.portal = portal

    def buildProtocol(self, addr):
        p = protocol.ServerFactory.buildProtocol(self, addr)
        p.portal = self.portal
        return p

@implementer(portal.IRealm)
class Realm:
    def requestAvatar(self, avatarId, mind, *interfaces):
        if IProtocolUser in interfaces:
            if avatarId == checkers.ANONYMOUS:
                av = AnonymousUser()
            elif avatarId.isupper():
                # Capitalized usernames are administrators.
                av = Administrator()
            else:
                av = RegularUser()
            return IProtocolUser, av, av.logout
        raise NotImplementedError("Only IProtocolUser interface is supported by this realm")

def main():
    r = Realm()
    p = portal.Portal(r)
    c = checkers.InMemoryUsernamePasswordDatabaseDontUse()
    c.addUser("auser", "thepass")
    c.addUser("SECONDUSER", "secret")
    p.registerChecker(c)
    p.registerChecker(checkers.AllowAnonymousAccess())

    f = ServerFactory(p)

    log.startLogging(sys.stdout)

    from twisted.internet import reactor
    reactor.listenTCP(4738, f)
    reactor.run()

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:0)

twisted.cred提供了一个抽象,允许您的应用程序独立于特定的验证方式开发一些凭据,并允许您的凭据数据库独立于您的应用程序进行开发。

在您的示例中,请注意您的应用程序代码(Protocol)如何不知道凭据纯粹存储在内存中的事实。如果用PAM后端,InMemoryUsernamePasswordDatabaseDontUse样式的数据库或者使用PostgreSQL的东西替换/etc-passwd,它同样不会意识到。

此外,这些用户名/密码后端都可以独立于您的应用程序逻辑进行开发 - 允许您的每个应用程序重复使用它们,无论它们是您的工作还是其他人与您共享的工作。