twisted的FTPRealm解读

来源:互联网 发布:正版spss软件多少钱 编辑:程序博客网 时间:2024/06/06 13:24

首先看下我的测试代码

from twisted.protocols.ftp import FTPFactory, FTPRealmfrom twisted.cred.portal import Portalfrom twisted.cred.checkers import AllowAnonymousAccess, FilePasswordDBfrom twisted.internet import reactorfrom twisted.internet import endpoints#pass.dat the same directory with ftp01.py# =====================# jeff:bozo# grimmtooth:bozo2# =====================#p = Portal(FTPRealm(anonymousRoot='E:/', userHome='E:/'),           [AllowAnonymousAccess(), FilePasswordDB("pass.dat")])f = FTPFactory(p)endpoints.serverFromString(reactor,'tcp:21').listen(f)reactor.run()


Portal类是cred的认证类,是用户登陆认证入口,通过Portal来构造一个FTPFactory提供TCP的服务(FTP,FTP是建立在TCP基础上的)。

FTPRealm是从BaseFTPRealm派生,BaseFTPRealm实现了portal.IRealm的接口。

class BaseFTPRealm:    """    Base class for simple FTP realms which provides an easy hook for specifying    the home directory for each user.    """    implements(portal.IRealm)    def __init__(self, anonymousRoot):        self.anonymousRoot = filepath.FilePath(anonymousRoot)    def getHomeDirectory(self, avatarId):        """        Return a L{FilePath} representing the home directory of the given        avatar.  Override this in a subclass.        @param avatarId: A user identifier returned from a credentials checker.        @type avatarId: C{str}        @rtype: L{FilePath}        """        raise NotImplementedError(            "%r did not override getHomeDirectory" % (self.__class__,))    def requestAvatar(self, avatarId, mind, *interfaces):        for iface in interfaces:            if iface is IFTPShell:                if avatarId is checkers.ANONYMOUS:                    avatar = FTPAnonymousShell(self.anonymousRoot)                else:                    avatar = FTPShell(self.getHomeDirectory(avatarId))                return (IFTPShell, avatar,                        getattr(avatar, 'logout', lambda: None))        raise NotImplementedError(            "Only IFTPShell interface is supported by this realm")

如果是匿名用户请求登陆则返回FTPAnonymousShell,否则返回FTPShell。这里FTPBaseRealm在用户登陆的时候直接以getHomeDirectory()作为FTP用户访问的根目录。

在看看FTPRealm,重写了getHomeDirectory,根据avatarId来返回一个子目录,这里特别要注意的是avatarId也就是FTP账号登陆的用户名。所以如果指定了userHome路径以后,还需要以用户名称来组织一个目录,这样才能让该用户正确访问到。

class FTPRealm(BaseFTPRealm):    """    @type anonymousRoot: L{twisted.python.filepath.FilePath}    @ivar anonymousRoot: Root of the filesystem to which anonymous        users will be granted access.    @type userHome: L{filepath.FilePath}    @ivar userHome: Root of the filesystem containing user home directories.    """    def __init__(self, anonymousRoot, userHome='/home'):        BaseFTPRealm.__init__(self, anonymousRoot)        self.userHome = filepath.FilePath(userHome)    def getHomeDirectory(self, avatarId):        """        Use C{avatarId} as a single path segment to construct a child of        C{self.userHome} and return that child.        """        return self.userHome.child(avatarId)

现在在反过来看看我例子里面的文件系统目录,匿名用户目录和用户目录都是E:盘,如果是匿名用户访问则直接访问E盘,否则如果是其他用户访问则访问的是E:\{用户名}目录。Portal的第二个参数指定了,用户的访问权限,可以匿名访问,而且可以通过文件密码的形式来访问,文件密码的格式(按照行),用户名:密码

[AllowAnonymousAccess(), FilePasswordDB("pass.dat")

这样通过几行代码就实现了一个简单的文件服务器了。也可以通过实现portal.IRealm接口来自定制访问权限。

1 0
原创粉丝点击