Comments 56
А колеса-то у Вас квадратные linux.die.net/man/8/pure-ftpd :)
+12
Юзеры в MySQL. Месье знает толк в извращениях.
-12
Базу можно подобрать под себя любую.
0
Why not?
Я вот не вижу каких-то однозначных причин не использовать mysql для этих целей.
Другое дело пароли в открытом виде, но и для этого могут быть причины.
Я вот не вижу каких-то однозначных причин не использовать mysql для этих целей.
Другое дело пароли в открытом виде, но и для этого могут быть причины.
+2
а кто мешает хранить их в MD5?
Можно сказать, что это прототип.
Можно сказать, что это прототип.
0
да конечно не что не мешает.
это я написал в тему, что уж если хочется придраться, то лучше к этому чем к mysql — тут хоть какую-то причину придумать можно
это я написал в тему, что уж если хочется придраться, то лучше к этому чем к mysql — тут хоть какую-то причину придумать можно
+1
Иногда нужно интегрировать FTP с существующей базой пользователей на Mysql или другой. В этом случае проще использовать СУБД напрямую чем через md5/sqllite
+1
А кто сказал что mySQL не подходит. Гвозди тоже можно микроскопом забивать. А какие у mySQL преимущества перед другими бд для хранения паролей?
-6
зависит от условий
пускай юзеров 100 000 и они пытаются поддерживать фтп соединение по фиговым каналам. лучше в plain text хранить?
а если учесть что на сервере скорее всего уже стоит mysql, то чем лучше тот sqlite или plain text?
в каком месте myisam на микроскоп для гвоздей похож?
пускай юзеров 100 000 и они пытаются поддерживать фтп соединение по фиговым каналам. лучше в plain text хранить?
а если учесть что на сервере скорее всего уже стоит mysql, то чем лучше тот sqlite или plain text?
в каком месте myisam на микроскоп для гвоздей похож?
0
Чем mySQL лучше других БД для хранения паролей? И какая разница сколько юзеров?
-7
А чем хуже?
+1
MySQL — реляционная СУБД. Зачем к примеру вам для хранения паролей все плюшки mySQL? Это и есть забивание гвоздей микроскопом. Или вы считаете что использовать сервер вместо калькулятора тоже гуд?
-7
А если так.
Есть сервис.
В нем есть пользователи, хранятся в БД (например в MySQL).
Сервис начинает предоставлять дополнительную услугу — доступ к удаленной директории по FTP. Что лучше держать пользователей в базе и синхронизировать его с файлом, в котором будут хранится пользователи, или добавить пару полей в базу?
Есть сервис.
В нем есть пользователи, хранятся в БД (например в MySQL).
Сервис начинает предоставлять дополнительную услугу — доступ к удаленной директории по FTP. Что лучше держать пользователей в базе и синхронизировать его с файлом, в котором будут хранится пользователи, или добавить пару полей в базу?
+1
за тем, что скорее она уже есть и за тем, что если Вы будете велосипедить подобным образом, то скорее всего для интеграции фтп в некую систему.
где хранить имя, фамилию, статистику использования квоты, список загруженного и т.д.?
где хранить имя, фамилию, статистику использования квоты, список загруженного и т.д.?
0
встроеный в питон sqlite наверно подошел бы лучше.
0
честно говоря думал такие статьи остались в начале 2000-х
+7
хотя, как учебный пример наверное хорошо
0
Да ладно вам, хорошо. Использовать old style классы — моветон, использовать 1 и 0 в качестве булевского выражения — моветон, писать
вместо
бессмысленно и в 4 раза дольше.
Про то, что там в sql запросы передается данные переданные пользователем, без всякого эскейпинга, я уже не говорю — sql injection это сейчас модно в обучающих статьях, как я понимаю.
Зачем такое использовать в качестве учебного примера?
if 'id' in data: return data['id'] else: return None
вместо
return data.get('id')
бессмысленно и в 4 раза дольше.
Про то, что там в sql запросы передается данные переданные пользователем, без всякого эскейпинга, я уже не говорю — sql injection это сейчас модно в обучающих статьях, как я понимаю.
Зачем такое использовать в качестве учебного примера?
+8
обучение не начинают с sql injection и остального, в обучении главное наглядность, а не фунциональность
+2
Делаю смелый вывод что Вы python-программист, и совсем не начального уровня.
Если не сложно скиньте несколько ссылок на полезные статьи (лучше в личку может даже).
Буду очень благодарен. Я не профи я только учусь, поэтому буду рад любому материалу.
Если не сложно скиньте несколько ссылок на полезные статьи (лучше в личку может даже).
Буду очень благодарен. Я не профи я только учусь, поэтому буду рад любому материалу.
0
Слушайте, это не было наездом на то, что вы чего-то не знаете. Простите если вам так показалось. Мы все вначале пишем плохой код, делаем детские ошибки и прочая — это совершенно нормально. Меня просто удивляют постоянно появляющиеся на главной хабра статьи начинающиеся словами «Я начал изучать python(ruby,java,lisp...) неделю назад и решил написать статью ...».
Что касается статей, то черт его знает. Я, помнится, читал что-то из стандартного набора Learninig P. Dive into P. и Python Cookbook.
Вообще, мне кажется надо просто читать много чужого кода написанного опытными людьми и параллельно официальную питоновскую документацию. Я, когда начинал, копался в коде twisted. Код самих питоновских библиотек можно смотреть. Иногда забавно в код самого питона заглянуть. Парни из pocoo.org пишут очень хорошие либы. Пользуетесь django — читайте джанго, не знаю, правда, что там.
Плюс англоязычные блоги — можно начать с planet python, а потом сами разберетесь кого читать.
Что касается статей, то черт его знает. Я, помнится, читал что-то из стандартного набора Learninig P. Dive into P. и Python Cookbook.
Вообще, мне кажется надо просто читать много чужого кода написанного опытными людьми и параллельно официальную питоновскую документацию. Я, когда начинал, копался в коде twisted. Код самих питоновских библиотек можно смотреть. Иногда забавно в код самого питона заглянуть. Парни из pocoo.org пишут очень хорошие либы. Пользуетесь django — читайте джанго, не знаю, правда, что там.
Плюс англоязычные блоги — можно начать с planet python, а потом сами разберетесь кого читать.
+2
Когда только учитесть, старайтесь хотябы первое время свой код не вывешивать на главной хабра, многие могут скопировать неглядя просто или подумать что так и нужно.
Я знакомство с питоном отсюда начинал:
docs.python.org/tutorial/index.html
Потом уже код простеньких программок из Ubuntu смотрел
Я знакомство с питоном отсюда начинал:
docs.python.org/tutorial/index.html
Потом уже код простеньких программок из Ubuntu смотрел
0
return data.get('id', None)
:)
:)
0
Оно и так по умолчанию None.
Class Docstring:
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
Class Docstring:
D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
0
этож бублгум!
в смысле pythonic way — должно быть читабельно и понятно любому, даже не программисту.
Поэтому первые несколько строк были лучше этой одной, но уж если одна, то хотя бы с полным описанием
P.S. PEP8 -> Programming Recommendations
в смысле pythonic way — должно быть читабельно и понятно любому, даже не программисту.
Поэтому первые несколько строк были лучше этой одной, но уж если одна, то хотя бы с полным описанием
P.S. PEP8 -> Programming Recommendations
0
Я, признаться, не осознал почему написать свой велосипед лучше, чем вызвать наистандартнейшую функцию из core library. Вы другие стандартные функции тоже ручками переписываете для наглядности?
Опять же — перечитал PEP8 -> Programming Recommendations и не нашел ни малейшего упоминания о том, что не рекомендуется использовать значения по умолчанию.
Более того — сделав grep по исходникам питона, я не нашел ни одного случая чтобы там использовали get("...", None) для хешей. Просто вызовов .get(key) зато там навалом. Не все они, конечно, вызываются на dict, но какая-то часть — наверняка.
И вообще мне кажется сомнительной мысль, что разработчики бы реализовывали функцию get, а потом не рекомендовали ее использовать.
Опять же — перечитал PEP8 -> Programming Recommendations и не нашел ни малейшего упоминания о том, что не рекомендуется использовать значения по умолчанию.
Более того — сделав grep по исходникам питона, я не нашел ни одного случая чтобы там использовали get("...", None) для хешей. Просто вызовов .get(key) зато там навалом. Не все они, конечно, вызываются на dict, но какая-то часть — наверняка.
И вообще мне кажется сомнительной мысль, что разработчики бы реализовывали функцию get, а потом не рекомендовали ее использовать.
0
в каком месте была стандартная фукнция переписана?
А по поводу грепа я не понял… толи Вы им пользоваться не умеете, толи врётё… хотя я думаю, просто другие исходники использовали
Python-2.7.1\Doc\tools\rstlint.py (1 hits)
Line 194: checkerlist = checkers.get(ext, None)
А по поводу грепа я не понял… толи Вы им пользоваться не умеете, толи врётё… хотя я думаю, просто другие исходники использовали
Python-2.7.1\Doc\tools\rstlint.py (1 hits)
Line 194: checkerlist = checkers.get(ext, None)
0
Ну если я удаляю вызов системной функции, и вставляю свои пять строк которые делают то же самое, то я это называю переписывать.
Вы ведь, к примеру, вызываете any, а не итерируете массив? Используете defaultdict, а не делаете вручную проверки и присвоения?
ух ты. Вы правы, видимо не умею. Пропустил пробел после запятой. Причем если бы я не нашел ничего, я бы заподозрил что-то, но увы, питонисты тоже иногда забывают ставить пробелы. Посыпаю голову пеплом и снимаю этот аргумент.
В любом случае — если бы авторы считали что этот параметр нужно явно указывать, они бы не сделали его опциональным.
Вы ведь, к примеру, вызываете any, а не итерируете массив? Используете defaultdict, а не делаете вручную проверки и присвоения?
ух ты. Вы правы, видимо не умею. Пропустил пробел после запятой. Причем если бы я не нашел ничего, я бы заподозрил что-то, но увы, питонисты тоже иногда забывают ставить пробелы. Посыпаю голову пеплом и снимаю этот аргумент.
В любом случае — если бы авторы считали что этот параметр нужно явно указывать, они бы не сделали его опциональным.
0
> как учебный пример
Если только пример «как нельзя», потому что код — ппц.
Если только пример «как нельзя», потому что код — ппц.
0
Каждый второй фтп-сервер поддерживает если не внешние аутентификаторы, то базу юзеров во внешней СУБД.
Велосипед.
Велосипед.
+2
А если нужно повесить триггеры на события по FTP? Например по факту закачки файла или создания директории, выполнять какую-либо функцию. Ни одно стандартное решение не поддерживает это лучше чем путь переопределения методов pyftpd.
0
Тем временем обычные пользователи пользуются тем же пресловутым ProFTPd, хранят доступы в базе, да еще и квоты заодно
+1
Поддержу предыдущего оратора про proftpd. Годы назад для нее уже сделали модуль для работы с mysql. Сам пакет стабилен, и все у него хорошо. Писать собственный — ну разве что из спортивного интереса
+1
тогда уж лучше vsftpd, имхо
0
Опыта общения с vsftpd не имел, поэтому пишу о том, о чем знаю. Кроме того, к proftpd есть графическая морда — gproftpd, которая позволяет достаточно удобно добавлять/удалять пользователей. Так что, если не нужно динамическое добавление, то можно использовать эту утилиту и не привязываться в базам. Одним словом, хорошо подходит для домашнего использования
0
Я в общем то тоже не имел с ним дела, но основное преимущество того же ProFTPd в том, что он перкрасно работает «из-коробки» в Debian. Минимум допиливания и конфиги Apache-style доставляю сильнее. На саом деле, когда серверов в проекте переваливает штук за 20-30 — начинает сказываться «цена» обслуживания. Под цено я имею ввиду не только зарплату сисадмина, а еще и время, которое требуется на настройку всего добра. Цепляние же базы к нему — прекрасно описано, и более того — запросы для работы с табличками вы делаете сами — и соответственно можете привязываться вообще к любой существующей табличке любого другого проекта, что мы и сделали лет этак 6 назад
0
Поднимать демон на скриптовом языке python — моветон. ftp-сервера с поддержкой mysql и настройкой портов есть уже много-много лет. Поздравляем Вас с разморозкой.
0
Ооо… А еще говорят что в питоне говнокода нет))
Может я немного преувеличиваю, но уж больно страшно смотрится:
* Зачем обертка над БД? db2 API сам себе прекрасная переносимая обертка (т.е. все реляционные БД в Python должны поддерживать этот интерфейс, см www.python.org/dev/peps/pep-0249/). А так получилась универсальная обертка над универсальной оберткой
* SQL инъекции привет!
* Чтоб получить last insert id существует атрибут .lastrowid курсора (см тот же PEP)
* про if return else return уже заметили
Может я немного преувеличиваю, но уж больно страшно смотрится:
* Зачем обертка над БД? db2 API сам себе прекрасная переносимая обертка (т.е. все реляционные БД в Python должны поддерживать этот интерфейс, см www.python.org/dev/peps/pep-0249/). А так получилась универсальная обертка над универсальной оберткой
* SQL инъекции привет!
sql = "select * from `users` where `username`='%s' and `password`='%s'" % (username,password)
Так в питоне не делают. Используют метод db.execute() с параметрами вроде db.execute(«select * from `users` where `username`='%s' and `password`='%s'», (username,password)) который автоматически экранирование добавляет* Чтоб получить last insert id существует атрибут .lastrowid курсора (см тот же PEP)
* про if return else return уже заметили
0
Когда изучал питон наткнулся на эту библиотеку… Написал свой авторизатор для mysql тогда.
Могу сразу сказать, что Вас ожидает ошибка mysql server has gone away :).
еще у Вас нет setuid и setgid.
Могу сразу сказать, что Вас ожидает ошибка mysql server has gone away :).
еще у Вас нет setuid и setgid.
0
Почему меня ожидает ошибка «mysql server has gone away»?
Про setuid и setgid можно подробнее.
Про setuid и setgid можно подробнее.
0
Прилечу домой скину авторизатор.
Запустите фтпд и авторизуйтесь, после этого оставьте на часов 8 в idle. после этого посыпятся ошибки mysql server has gone away.
Запустите фтпд и авторизуйтесь, после этого оставьте на часов 8 в idle. после этого посыпятся ошибки mysql server has gone away.
0
Как и обещал, полный листинг, дыр я вроде не находил, т.к. все в escapestring. Пароль сами завернуть можете в md5 надеюсь…
import pwd,os,MySQLdb
class MysqlAuthorizer(ftpserver.DummyAuthorizer):
PROCESS_UID = os.getuid()
PROCESS_GID = os.getgid()
ml = None
def __init__(self, ml={'user':'','passwd':'','db':'','host':''}):
if ml['host'].startswith("/"):
ml['us'] = ml['host']
ml['host'] = 'localhost'
self.ml = ml
self.connect()
return
def connect(self):
ml = self.ml
try:
db=MySQLdb.connect(host=ml['host'],user=ml['user'],passwd=ml['passwd'],db=ml['db'],unix_socket=ml['us'])
self.c = db.cursor()
except:
return
def add_user():
return
def add_anonymous():
return
def remove_user():
return
def impersonate_user(self, username, password):
try:
self.c.execute(«SELECT uid FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
except:
self.connect()
self.c.execute(«SELECT uid FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
re = self.c.fetchone()
t = pwd.getpwuid(re[0])
os.setegid(t.pw_gid)
os.seteuid(t.pw_uid)
def terminate_impersonation(self):
os.setegid(self.PROCESS_GID)
os.seteuid(self.PROCESS_UID)
def validate_authentication(self, username, password):
try:
self.c.execute(«SELECT id FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
except:
self.connect()
self.c.execute(«SELECT id FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
return self.c.rowcount
def has_user(self, username):
try:
self.c.execute(«SELECT id FROM users WHERE user = %s LIMIT 1», (username,))
except:
self.connect()
self.c.execute(«SELECT id FROM users WHERE user = %s LIMIT 1», (username,))
return self.c.rowcount
def has_perm(self, username, perm, path=None):
try:
self.c.execute(«SELECT id FROM users WHERE user = %s AND perm LIKE %s LIMIT 1», (username,''.join(['%',perm,'%'])))
except:
self.connect()
self.c.execute(«SELECT id FROM users WHERE user = %s AND perm LIKE %s LIMIT 1», (username,''.join(['%',perm,'%'])))
return self.c.rowcount
def get_perms(self, username):
try:
self.c.execute(«SELECT perm FROM users WHERE user = %s LIMIT 1», (username,))
except:
self.connect()
self.c.execute(«SELECT perm FROM users WHERE user = %s LIMIT 1», (username,))
re = self.c.fetchone()
return re[0].strip(",")
def get_home_dir(self, username):
try:
self.c.execute(«SELECT homedir FROM users WHERE user = %s LIMIT 1», (username,))
except:
self.connect()
self.c.execute(«SELECT homedir FROM users WHERE user = %s LIMIT 1», (username,))
re = self.c.fetchone()
return re[0]
def get_msg_login(self, username):
return «Hallo!»
def get_msg_quit(self, username):
return «Bye bye...»
import pwd,os,MySQLdb
class MysqlAuthorizer(ftpserver.DummyAuthorizer):
PROCESS_UID = os.getuid()
PROCESS_GID = os.getgid()
ml = None
def __init__(self, ml={'user':'','passwd':'','db':'','host':''}):
if ml['host'].startswith("/"):
ml['us'] = ml['host']
ml['host'] = 'localhost'
self.ml = ml
self.connect()
return
def connect(self):
ml = self.ml
try:
db=MySQLdb.connect(host=ml['host'],user=ml['user'],passwd=ml['passwd'],db=ml['db'],unix_socket=ml['us'])
self.c = db.cursor()
except:
return
def add_user():
return
def add_anonymous():
return
def remove_user():
return
def impersonate_user(self, username, password):
try:
self.c.execute(«SELECT uid FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
except:
self.connect()
self.c.execute(«SELECT uid FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
re = self.c.fetchone()
t = pwd.getpwuid(re[0])
os.setegid(t.pw_gid)
os.seteuid(t.pw_uid)
def terminate_impersonation(self):
os.setegid(self.PROCESS_GID)
os.seteuid(self.PROCESS_UID)
def validate_authentication(self, username, password):
try:
self.c.execute(«SELECT id FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
except:
self.connect()
self.c.execute(«SELECT id FROM users WHERE user = %s AND passwd = %s LIMIT 1», (username,password))
return self.c.rowcount
def has_user(self, username):
try:
self.c.execute(«SELECT id FROM users WHERE user = %s LIMIT 1», (username,))
except:
self.connect()
self.c.execute(«SELECT id FROM users WHERE user = %s LIMIT 1», (username,))
return self.c.rowcount
def has_perm(self, username, perm, path=None):
try:
self.c.execute(«SELECT id FROM users WHERE user = %s AND perm LIKE %s LIMIT 1», (username,''.join(['%',perm,'%'])))
except:
self.connect()
self.c.execute(«SELECT id FROM users WHERE user = %s AND perm LIKE %s LIMIT 1», (username,''.join(['%',perm,'%'])))
return self.c.rowcount
def get_perms(self, username):
try:
self.c.execute(«SELECT perm FROM users WHERE user = %s LIMIT 1», (username,))
except:
self.connect()
self.c.execute(«SELECT perm FROM users WHERE user = %s LIMIT 1», (username,))
re = self.c.fetchone()
return re[0].strip(",")
def get_home_dir(self, username):
try:
self.c.execute(«SELECT homedir FROM users WHERE user = %s LIMIT 1», (username,))
except:
self.connect()
self.c.execute(«SELECT homedir FROM users WHERE user = %s LIMIT 1», (username,))
re = self.c.fetchone()
return re[0]
def get_msg_login(self, username):
return «Hallo!»
def get_msg_quit(self, username):
return «Bye bye...»
0
0
Sign up to leave a comment.
FTP сервер с авторизацией через базу данных