標籤:twisted ftp
首先看下我的測試代碼
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介面來自定製存取權限。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
twisted的FTPRealm解讀