データベース認証付きFTPサーバー
 
      
        
        
        
      
    
      
        
        
        
      
     サーバーに展開するための既製のFTPサーバーが多数あります。 しかし、FTPがサーバー上ですでに実行されているため、代替ポートでFTPサーバーを上げる必要がありました。 また、ユーザーがファイルのあるフォルダにのみアクセスできるようにします。  Pythonツールを使用して何ができるかを尋ねることにしました。 検索はすぐにpyFTPdライブラリを返しました。 
      
        
        
        
      
    
      
        
        
        
      
    
      
        
        
        
      
     このライブラリの既製の例は、FTPサーバーを数分で上げる方法を示しています。 ユーザーとユーザーがアクセスできるファイルへのパスは、データベースに保存されます。 したがって、このライブラリーを基礎としてデータベースにリンクすることが決定されました。 そして、あなた自身のグッズを備えたFTPサーバーを入手してください:) 
      
        
        
        
      
    
      
        
        
        
      
     データベース 
      
        
        
        
      
     データベース内のテーブルは、複雑なものを超えるものを表しません。 
      
        
        
        
      
      SQL: 
      
        
        
        
      
    CREATE TABLE ` users ` ( 
      
        
        
        
      
     ` id ` int ( 11 ) NOT NULL auto_increment, 
      
        
        
        
      
     ` username ` varchar ( 255 ) NOT NULL , 
      
        
        
        
      
     ` password ` varchar ( 32 ) NOT NULL , 
      
        
        
        
      
     ` path ` varchar ( 255 ) NOT NULL , 
      
        
        
        
      
     ` perm ` varchar ( 8 ) default NULL , 
      
        
        
        
      
     PRIMARY KEY ( ` id ` ), 
      
        
        
        
      
     KEY ` username ` ( ` username ` ) 
      
        
        
        
      
     ) 
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
    
      
        
        
        
      
     使用される主なパラメーターは、ログイン、パスワード、アクセス権、ユーザーがアクセスできるフォルダーへのパスです。 
      
        
        
        
      
    
      
        
        
        
      
     実装 
      
        
        
        
      
     すぐに行われた最初のことは、データベースを操作するための小さなクラスラッパーでした。 したがって、ニーズに合わせて書き直して、MySQLを任意のデータベースに置き換えることができます。 
      
        
        
        
      
    
      
        
        
        
      
     class DB : 
      
        
        
        
      
     
      
        
        
        
      
     init = None 
      
        
        
        
      
     db = None 
      
        
        
        
      
     def __init__ ( self ,init_db): 
      
        
        
        
      
     """ Constructor """ 
      
        
        
        
      
     self . init = init_db 
      
        
        
        
      
     self . db = self . init() 
      
        
        
        
      
     
      
        
        
        
      
     def doSql ( self ,sql): 
      
        
        
        
      
     """ Handle SQL """ 
      
        
        
        
      
     try : 
      
        
        
        
      
     self . db . execute(sql) 
      
        
        
        
      
     except : 
      
        
        
        
      
     try : 
      
        
        
        
      
     self . db = self . init() 
      
        
        
        
      
     self . db . execute(sql) 
      
        
        
        
      
     except : 
      
        
        
        
      
     print "error:" + sql 
      
        
        
        
      
     
      
        
        
        
      
     def getDB ( self ): 
      
        
        
        
      
     """ """ 
      
        
        
        
      
     return self . db 
      
        
        
        
      
     
      
        
        
        
      
     def getLastId ( self ): 
      
        
        
        
      
     """Get last insert ID""" 
      
        
        
        
      
     sql = "select LAST_INSERT_ID() as `id`" 
      
        
        
        
      
     self . doSql(sql) 
      
        
        
        
      
     data = self . db . fetchone() 
      
        
        
        
      
     if 'id' in data: 
      
        
        
        
      
     return data[ 'id' ] 
      
        
        
        
      
     else : 
      
        
        
        
      
     return None 
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
    
      
        
        
        
      
     ウィキペディアとサーバー自体のソースコードを検討した結果、承認とファイルの場所の選択を担当するメソッドが特定されました。 その後、これらの方法を再定義する必要があり、問題は解決しました。 
      
        
        
        
      
     サーバーの起動方法は次のとおりです。 
      
        
        
        
      
     . . . 
      
        
        
        
      
     def starterver ( self ): 
      
        
        
        
      
     """Run server""" 
      
        
        
        
      
     authorizer = self . ftpserver . DummyAuthorizer() 
      
        
        
        
      
     
      
        
        
        
      
     authorizer . validate_authentication = self . my_validate_authentication 
      
        
        
        
      
     authorizer . get_home_dir = self . my_get_home_dir 
      
        
        
        
      
     authorizer . get_perms = self . my_get_perms 
      
        
        
        
      
     authorizer . get_msg_login = self . my_get_msg_login 
      
        
        
        
      
     authorizer . get_msg_quit = self . my_get_msg_quit 
      
        
        
        
      
     
      
        
        
        
      
     authorizer . has_perm = self . my_has_perms 
      
        
        
        
      
     authorizer . has_user = self . my_has_user 
      
        
        
        
      
     
      
        
        
        
      
     # Instantiate FTP handler class 
      
        
        
        
      
     ftp_handler = ftpserver . FTPHandler 
      
        
        
        
      
     ftp_handler . authorizer = authorizer 
      
        
        
        
      
     ftp_handler . passive_ports = range ( 63000 , 63500 ) 
      
        
        
        
      
     # Define a customized banner (string returned when client connects) 
      
        
        
        
      
     ftp_handler . banner = "pyftpdlib %s based ftpd ready." % ftpserver . __ver__ 
      
        
        
        
      
     
      
        
        
        
      
     address = ( '127.0.0.1' , 23 ) 
      
        
        
        
      
     ftpd = ftpserver . FTPServer(address, ftp_handler) 
      
        
        
        
      
     
      
        
        
        
      
     # set a limit for connections 
      
        
        
        
      
     ftpd . max_cons = 256 
      
        
        
        
      
     ftpd . max_cons_per_ip = 5 
      
        
        
        
      
     
      
        
        
        
      
     # start ftp server 
      
        
        
        
      
     ftpd . serve_forever() 
      
        
        
        
      
     . . . 
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
    
      
        
        
        
      
     オーバーライドされた主なメソッド 
      
        
        
        
      
    
      
        
        
        
      
      validate_authentication-ユーザー認証を担当します。 
      
        
        
        
      
      get_home_dir-ユーザーがアクセスできるホームディレクトリを取得します。 
      
        
        
        
      
      get_perms-データアクセス許可を取得します。 
      
        
        
        
      
      has_perm-ディレクトリへのユーザーアクセス権の確認 
      
        
        
        
      
      has_user-ユーザーの存在を確認します 
      
        
        
        
      
    
      
        
        
        
      
     ユーザーと連携するために、別のクラスが実装されました。 
      
        
        
        
      
     from db import DB 
      
        
        
        
      
     from config import init_db 
      
        
        
        
      
     class User : 
      
        
        
        
      
     
      
        
        
        
      
     def __init__ ( self ): 
      
        
        
        
      
     """Init""" 
      
        
        
        
      
     
      
        
        
        
      
     def auth ( self ,username,password): 
      
        
        
        
      
     """Make auth""" 
      
        
        
        
      
     sql = "select * from `users` where `username`=' %s ' and `password`=' %s '" % (username,password) 
      
        
        
        
      
     db = DB(init_db) 
      
        
        
        
      
     db . doSql(sql) 
      
        
        
        
      
     res = db . getDB() . fetchone() 
      
        
        
        
      
     if res: 
      
        
        
        
      
     return 1 
      
        
        
        
      
     else : 
      
        
        
        
      
     return None 
      
        
        
        
      
     
      
        
        
        
      
     def getPath ( self ,username): 
      
        
        
        
      
     """Return path by username""" 
      
        
        
        
      
     sql = "select `path` from `users` where `username`=' %s '" % username 
      
        
        
        
      
     db = DB(init_db) 
      
        
        
        
      
     db . doSql(sql) 
      
        
        
        
      
     uparam = db . getDB() . fetchone() 
      
        
        
        
      
     if uparam: 
      
        
        
        
      
     return uparam[ 'path' ] 
      
        
        
        
      
     else : 
      
        
        
        
      
     return None 
      
        
        
        
      
     
      
        
        
        
      
     def getPerm ( self ,username): 
      
        
        
        
      
     """Return permission by username""" 
      
        
        
        
      
     sql = "select `perm` from `users` where `username`=' %s '" % username 
      
        
        
        
      
     db = DB(init_db) 
      
        
        
        
      
     db . doSql(sql) 
      
        
        
        
      
     uparam = db . getDB() . fetchone() 
      
        
        
        
      
     if uparam: 
      
        
        
        
      
     return uparam[ 'perm' ] 
      
        
        
        
      
     else : 
      
        
        
        
      
     return '' 
      
        
        
        
      
     
      
        
        
        
      
     def hasUser ( self ,username): 
      
        
        
        
      
     """Checj user into DB""" 
      
        
        
        
      
     sql = "select `id` from `users` where `username`=' %s '" % (username) 
      
        
        
        
      
     db = DB(init_db) 
      
        
        
        
      
     db . doSql(sql) 
      
        
        
        
      
     uparam = db . getDB() . fetchone() 
      
        
        
        
      
     if uparam: 
      
        
        
        
      
     return 1 
      
        
        
        
      
     else : 
      
        
        
        
      
     return 0 
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
    
      
        
        
        
      
     必要なメソッドをラップします。 
      
        
        
        
      
     def my_validate_authentication ( self ,username,password): 
      
        
        
        
      
     return User() . auth(username, password) 
      
        
        
        
      
     
      
        
        
        
      
     def my_get_home_dir ( self ,username): 
      
        
        
        
      
     return User() . getPath(username) 
      
        
        
        
      
     
      
        
        
        
      
     def my_get_perms ( self ,username): 
      
        
        
        
      
     return User() . getPerm(username) 
      
        
        
        
      
     
      
        
        
        
      
     def my_get_msg_login ( self ,username): 
      
        
        
        
      
     return 'hello msg login' 
      
        
        
        
      
     
      
        
        
        
      
     def my_get_msg_quit ( self ,username): 
      
        
        
        
      
     return 'byu msg quit' 
      
        
        
        
      
     
      
        
        
        
      
     def my_has_user ( self ,username): 
      
        
        
        
      
     return User() . hasUser(username) 
      
        
        
        
      
     
      
        
        
        
      
     def my_has_perms ( self ,username, perm, path = None ): 
      
        
        
        
      
     return 1 
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
    
      
        
        
        
      
     結果 
      
        
        
        
      
     ユーザーはデータベースを介してログインし、自分のディレクトリにアクセスします。 
      
        
        
        
      
    
      
        
        
        
      
     改善できるもの 
      
        
        
        
      
     キャッシュを使用して、データベース呼び出しをオフロードできます。 たとえば、memcache。 ここには非常に多くのオプションがあります: 
      
        
        
        
      
    -  ユーザーがログインするときに、ユーザーに関するすべての情報をキャッシュに書き込み、そこから読み取ります 
-  ユーザーデータベースをキャッシュに保存し、定期的に更新する 
 ソースコード 
      
        
        
        
      
     ソースコードは
こちらからダウンロードでき
ます 。 
      
        
        
        
      
    
      
        
        
        
      
     ソース 
      
        
        
        
      
      http://en.wikipedia.org/wiki/File_Transfer_Protocol 
      
        
        
        
      
      http://code.google.com/p/pyftpdlib/ 
        
        
        
      
    
All Articles