データベース認証付き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