Предыстория
Осень 2015-ого. Примерно полтора года назад, когда мне случилось стать участником разработки проекта, где пользователей существенно больше пары десятков человек, я наконец-то впервые в своей жизни задумался о надёжности авторизации.
По сути, авторизация — это то, с чего начинается процесс взаимодействия зарегистрированного пользователя с системой (для незарегистрированного пользователя всё начинается с регистрации, и эти два процесса, как вы уже догадались, очень сильно взаимосвязаны). Я внезапно осознал, что во всех проектах, что я делал до этого, с безопасностью всё очень плохо.
Достаточно рассмотреть простейший пример: кто-то подобрал пароль, или человек каким-то образом скомпрометировал его. Конечно, у нас в базе данных хранятся хэши с использованием соли, мы даже настолько продвинуты, что используем только HTTPS… Но это никак не спасёт нас от человеческого фактора.
Что делает в случае взлома грамотная система? Блокирует аккаунт (совсем хорошо — если автоматически, по ряду необычных признаков в поведении пользователя), в дальнейшем предлагая средства для восстановления: привязанный телефонный номер, контрольный вопрос, и т.д. Привязка сотового — отличная мера с крайне высокой надёжностью. К сожалению, у нашего проекта не было на это средств, поэтому приходилось обходиться без этого. Благо, блокировку можно реализовать, посадив человека на специальный почтовый ящик, или даже принимать экстренные звонки на сотовый.
И тут традиционный метод, который применяют многие начинающие разработчики (найденный в книгах, либо в статьях в интернете) даёт осечку. Дело в том, что этот метод предполагает хранение авторизации в сессиях. Это статья не относится к конкретному языку, и справедлива для любой платформы, но я буду иллюстрировать всё на примере PHP.
Стандартная реализация
Итак, сессия в PHP по умолчанию хранится в файле. Её id сохраняется в cookie (если куки отключены — задействуется механизм передачи через адресную строку, если это не отключено в конфигурации). Время жизни такой сессионной куки по умолчанию — до момента закрытия браузера (и обычно его никто не меняет). Поэтому более продвинутые программисты реализуют галочку «запомнить меня», либо реализуют её функционал по умолчанию, без возможности отключить. Что они делают? Просто сохраняют в собственной куке айди пользователя. Но поскольку просто айди хранить как-то уж слишком стрёмно (любой может поставить любое число и получить доступ к произвольному аккаунту), то часто вместе с айди за компанию сохраняют и пароль. В открытом виде.
Если кто-то не понимает, чем это плохо — представьте себе, что у нас пользователь пользуется очень старым, либо очень плохо реализованным браузером. Мы ведь не можем гарантировать, что браузер надёжно шифрует куки? Да и вирусы всякие могут быть у пользователя на компьютере, и в случае особо серьёзной малвари может не спасти и шифровка — зловред может попытаться считать значения прямо из памяти, когда они расшифрованы. Человек, случайно оказавшийся у вашего компьютера в ваше отсутствие — сможет просто скопировать себе все интересующие куки, и в новых браузерах этот процесс стал ещё проще. Дыры в безопасности браузера могут потенциально привести к тому, что ваша кука станет доступна стороннему сайту (да, сейчас это крайней маловероятно, но чем чёрт не шутит).
Ну и самое главное — если у нас SSL используется только при авторизации (а на остальных страницах его решили отключить ради выигрыша в скорости, либо чтобы лучше работало промежуточное кэширование)… То наш пароль всё время передаётся открытым текстом. При каждом запросе. А пароль меняют редко, то есть это некий токен, который имеет долгий срок жизни. А теперь представим себе, что наш трафик кто-то перехватил…
Как быть?
Очевидно, с этим надо что-то делать. Да, можно сразу бежать покупать сертификат и подключать SSL. Но можно сделать кое-что ещё до этого, и существенно снизить тем самым необходимость в нём. В конце концов, в том же ВКонтакте SSL стал принудительным всего полгода назад, а до этого как-то ведь жили.
Первое, что приходит на ум — хранить вместо пароля хэш от него. Это не особо поможет, если кто-то перехватит трафик, и не поможет при краже кук. Но вот в ситуации «кто-то открыл настройки и прошёлся по кукам, пытаясь запомнить значения» — сильно усложнит жизнь злоумышленнику.
Можно пойти дальше, и при создании хэша использовать юзер-агент. Теперь взломщику придётся использовать браузер той же версии, что и у нас (а в случае с IE ещё и с тем же набором плагинов тех же самых версий, что выходит уж очень маловероятно, особенно если взломщик не догадался подсмотреть юзер-агент).
Но если пароль всё же утёк — мы по-прежнему бессильны. Даже сменив пароль через форму восстановления либо изнутри системы — взломщик останется залогинен, пока не закроет браузер. Ведь в основе авторизации у нас всё ещё лежит сессия.
Можно, конечно, на PHP получить id сессии при логине, записать его куда-то в базу, а при сбросе пароля стартовать по очереди все сессии с айдишниками из базы и делать session_destroy()… Возможный вариант, но не обязательно следовать ему.
Итак, мы сформулировали основной список требований к нашей системе:
1. Быть простой в реализации
2. Желательно не зависеть от используемой серверной платформы
3. Позволить «выкинуть» взломщика из системы, завершив все открытые сессии, либо некоторые из них (на основе браузера/операционной системы/времени логина)
4. Видеть список всех своих открытых сессий в системе, просматривать его
5. Максимально затруднить атаку в случае отсутствия SSL (например, открытый Wi-Fi)
6. Не создавать неудобств легитимным пользователям
Приступаем к работе
Перво-наперво создадим в нашей базе данных (будем считать, что мы используем реляционную СУБД) таблицу для хранения сессий. Наших сессий (не путать с PHP-шными!). Таблица будет иметь следующие поля: id, user_id, ip, user_agent, time. В качестве времени будем хранить время создания сессии. Можно хранить и время последнего доступа, но вскоре мы увидим, что это избыточно, и можно к этому прибегнуть лишь в рамках денормализации, чтобы ускорить выборку данных. Создаваться сессия будет в момент авторизации, а также при регистрации (мы хотим, чтобы после регистрации пользователю не приходилось заполнять форму логина, и тут же авторизуем его). Также создадим вторую таблицу — log, с таким же набором полей. Туда будем добавлять запись при каждой авторизации (через форму входа или по кукам).
Теперь мы можем хранить на клиенте id сессии, и сверять его с базой. При этом сервер может проверить, что у нас совпадает юзер-агент и IP. Если хотя бы что-то одно не сходится — считаем, что пользователь не авторизован, и направляем его на страницу логина.
Но этого как-то мало — IP клиента взломщик может знать (и если он перехватывает трафик, то уж точно его знает), то же самое касается юзер-агента (который вообще получить не составляет никаких проблем). Нам хотелось бы хранить в cookie не пароль, а некую производную от пароля, привязанную к сессии… то есть к юзер-агенту и IP. Соответственно, если что-то стало отличаться — доступ прекратится. Поэтому, как вы уже догадались, разумно использовать хэш от этих переменных, и сохранять в куке его. При этом просто посмотрев на хэш, взломщик не только не сможет узнать пароль, но даже точно определить, какие именно компоненты были использованы при его создании (и с какими модификациями).
Создадим в таблице сессий ещё одну колонку — hash. Будем использовать её для хранения хэшей наших сессий.
Вопрос удобства
Но тут мы сталкиваемся с другой проблемой. Клиент может переключаться между разными IP (как минимум между домашним Wi-Fi и 3G в дороге, а ещё рабочим защищённым Wi-Fi, как пример). И было бы очень негуманно заставлять его вводить заново логин и пароль каждый раз при смене IP адреса. Как быть, хранить в куке целый список хэшей? При запросе на сервер отсылать его? Можно, но это несколько усложняет реализацию. Кроме того, это раздувает размер куки (при том, что нам основную часть времени может требоваться всего один хэш, мы будем хранить все когда-либо использовавшиеся), а при очистке кук мы (как пользователь) потеряем их все, и опять придётся с каждого IP адреса вводить пароль вручную.
Что, если привязать хэш только к юзер-агенту? Можно, но это существенно снизит безопасность. Нам нужен компромиссный подход.
Делегирование полномочий
Давайте попробуем создать отдельный модуль. Назовём его совершенно бесхитростно — security.php, и оформим как отдельный скрипт. Будем подключать его ко всем закрытым страницам нашего проекта в самом начале. Внутри этого файла будем анализировать некие условия, а по итогам его работы выставлять специальный флаг в 0 или 1. Пусть этот флаг будет храниться в переменных сессии (массив $_SESSION в PHP).
Что нам это даёт? Мы можем запихать в этот скрипт сколь угодно хитрую логику, вплоть до анализа последних действий пользователя и добавления его в бан-лист по IP, либо блокировки его аккаунта на тот или иной срок. Но сперва реализуем очень базовую функциональность: будем сверять значение хэша, пришедшего из куки, с тем, что должно было бы получиться, если хэш не был искажён. Сервер знает IP, знает юзер-агент, знает пароль текущего пользователя… Кажется, всё готово!
Разобьём начальную стадию нашего внешнего скрипта (это тоже можно вынести в отдельный файл, но в данный момент это не важно) на два этапа. На первом мы смотрим, установлена ли обычная сессия PHP. Если нет — сразу перебрасываем пользователя на форму авторизации. Но форма при загрузке проверяет наличие кук, и если кука с хэшем нашей сессии существует, и хэш совпадает с ожидаемым (хэш-функция от пароля* и юзер-агента), то ставим переменные сессии (в первую очередь user_id), делаем запись в таблицу log, и обратно перебрасываем пользователя туда, откуда он пришёл (адрес раздела для возврата разумно передавать прямо в ссылке). Итак, если нет PHP-сессии, но есть куки, и куки соответствуют браузеру — пользователь залогинен.
Теперь рассмотрим вариант, когда сессия есть (после того, как пользователь залогинен по паролю из формы или по кукам, он тоже попадёт на этот шаг). И вот тут вступает в игру наш скрипт security.php. Вот его код:
<?php
if ($_SESSION['security_check'] == 0) {
$user_id = $_SESSION['user_id'];
$n = (int)mysql_result(mysql_query("SELECT COUNT(*) FROM `sessions` ".
"WHERE `user_id`=".$user_id." AND `ip`='".$_SERVER['REMOTE_ADDR']."' ".
"AND `user_agent`='".mysql_real_escape_string($_SERVER['HTTP_USER_AGENT'])."' ".
"AND `hash`='".preg_replace("/[^0-9a-f]/", "", $_COOKIE['auth'])."'"), 0);
if ($n == 0) {
header("Location: /login?act=logout");
exit();
} else {
$_SESSION['security_check'] = 1;
}
}
//$n = mysql_result(mysql_query("SELECT COUNT(*) FROM `banned` WHERE `ip`='".$_SERVER['REMOTE_ADDR']."'"), 0);
//if ($n > 0) $_SESSION['security_check'] = 0;
?>
Если нам нужна система банов — можно раскомментировать последние две строки. И не забываем, что чтобы не произошло бесконечного зацикливания, в скрипт авторизации проверку на бан тоже надо включить!
Скрипт прост как дважды два. Мы проверяем наличие сессии с нашими текущими параметрами и нашим текущим хэшем. Если что-то не совпало — нас попросят пройти повторную авторизацию через редирект. И вот тут происходит самое вкусное. Если у нас поменялся только IP — мы пройдём проверку, для нас создастся новая сессия, если её нет для этого IP (этот момент надо включить в код авторизации), и создастся новая кука.
Если у нас поменялся браузер (угнанная кука) — придётся вводить пароль, которого у взломщика нет, иначе зачем ему воровать куки. При этом IP скорее всего будет другим, но может быть и тем же (взломщик находится с нами в одной локальной сети). В случае, когда взломщик в одной сети с жертвой, и имеет тот же юзер-агент — к сожалению, мы никак не сможем отличить его от настоящего пользователя. Привет, беспарольный Wi-Fi.
Если поменялся только хэш (поменяли куку вручную? побились файлы на жёстком диске?) — придётся авторизоваться заново, ничего не поделать.
Наконец, можно очень эффектно моментально отключить доступ к аккаунту. Для этого даже не обязательно удалять строку с сессией. Достаточно удалить/поменять/добавить один символ в хэше (последнее поле). Пример из жизни — если легитимный пользователь по счастливому стечению обстоятельств первым успеет воспользоваться кнопкой смены пароля в кабинете — взломщика выкинет, причём при первой же перезагрузке страницы. У настоящего пользователя уже будет новая кука (в хэше будет использован новый пароль), старые сессии будут полностью удалены из таблицы, а новая сессия создана с новым хэшем. А взломщик останется со старым невалидным хэшем, который не пройдёт проверку в security.php. При первом же непрохождении будет сброшена сессия PHP, и выполнен редирект на авторизацию. Которую, опять же, нельзя пройти, имея неактуальный хэш от старого пароля.
Всё хорошо?
Почти. Данная система по-прежнему не защищает от кражи хэша из кук при открытом канале и отсутствии SSL. Кроме того, сложно обеспечить своевременную блокировку, если доступ к аккаунту утерян (особенно если взломщик уже сменил пароль). В этом случае очень помог бы сброс пароля через смс-команду с привязанного телефона — но для этого уже нужна возможность принимать и отправлять смс. А если она есть — то можно сразу внедрить двухфакторную авторизацию, которая снимет массу проблем. Но не проблему с необходимостью в SSL — поскольку всё равно результатом любой авторизации является получение некого токена доступа, работающего ограниченное время. И этого времени может быть достаточно, чтобы сделать от нашего имени что-то, что нам не понравится.
Данный код можно, наверное, сделать ещё лучше и надёжнее. Если у вас есть по этому поводу соображения — пишите их в комментарии. Пока что система зарекомендовала себя с очень хорошей стороны, и была использована уже минимум в трёх проектах, два из которых имеют массовый доступ.
Комментарии (308)
akirsanov
12.03.2017 11:34+7"AND `user_agent`='".$_SERVER['HTTP_USER_AGENT']."' ".
sql injectionpopov654
12.03.2017 11:39faceplam(2)
Хотя это конечно очень не очевидно для стороннего человека, что такое вообще есть. Не зная исходников :)akirsanov
12.03.2017 11:40+2https://en.wikipedia.org/wiki/Security_through_obscurity
popov654
12.03.2017 12:09-3Примерно знал про это, хотя эту статью не читал ещё раньше. Здесь основной принцип был не в этом. Я просто к тому, что мало кому придёт в голову пихать SQL-инъекцию не в форму ввода или GET-параметр, а в куку. Да ещё именно в эту. Не зная исходников :)
JDBiber
12.03.2017 12:24+5мало кому придет в голову пихать инъекцию руками, а стандартный софтв Кали пихает сам во все вохможные и невозможные места
popov654
12.03.2017 12:46-3Не слышал про такой, но согласен, что лучше не допускать ни одной уязвимости. Тем более, когда тебе уже явно на неё показали. Исправлю этот момент.
На самом деле, сильно код не поменяется. Ну будет mysql_real_escape_string($_SERVER['HTTP_USER_AGENT']). Читать сложнее, пример же больше как учебный писался. Но в целом да, лучше сделать так. Согласен абсолютно здесь.ookami_kb
12.03.2017 13:18+18Примерно знать про security through obscurity, не слышать про kali, но при этом писать обучающую статью "Надежная авторизация". Вы серьезно?
А вообще, для начала можно было открыть код любого нормального фреймворка и посмотреть, как реализована авторизация в нем.
popov654
12.03.2017 14:34+1Но ведь интереснее попытаться придумать самому :) Если посмотреть, как сделано у других — есть шанс, что лучше придумать уже не получится. И в итоге просто скопируешь один в один.
m0Ray
12.03.2017 22:53+2Интереснее — не значит полезнее. Чтобы придумать лучше, надо как минимум понять, какие преимущества и недостатки есть у существующих решений. Попытаться понять, откуда растут недостатки и устранить их, постаравшись не добавить новых. В общем, обычная исследовательская, научная и творческая работа.
Но работа, а не «наскок». Придумать что-то гениальное «от балды» шанс исчезающе мал. И даже когда «от балды» что-то кем-то придумывается, обычно оказывается, что этот кто-то очень много времени и сил отдал изучению тематики, в которой случилась его «балда».
popov654
12.03.2017 14:34Статья не совсем обучающая, и она скорее рассчитана на самый начальный уровень… Я ни на что и не претендую как бы
tester_toster
12.03.2017 15:48Прочтите — Symfony день 1. Там есть момент:
Наверное вы читали подобное предупреждение:
«Не забудьте добавить валидацию и проверки на ошибки в реальном приложении.»
или
«Безопасность отдаётся на личное изучение читателя»
или
«Конечно, Вам придётся писать тесты»
Этим и отличается хороший учебный материал от плохого.popov654
12.03.2017 15:51А я всегда выполняю проверки на ошибки. То, что тут их не оказалось — это не система. А разовый недосмотр :)
Про безопасность — тоже очень мудро, пока сам шишек не набьёшь, не поймёшь, что нужно проверять, когда и зачем. Тоже кстати был опыт, на своих ошибках учился.
Насчёт тестов — пока как-то судьба миловала. Видимо, проекты не столь большие и сложные, обхожусь без них. Но иногда приходится прибегать к ухищрениям и разбивать алгоритм на составные этапы, тестируя каждый из них в отдельности, и лишь потом переходя к следующему, иначе просто велик риск получить полностью нерабочий код, отчаяться и опустить руки.
m0Ray
12.03.2017 17:12+2На самом деле лучше будет как-то так:
$mysqli=new mysqli('host','user','pass','base'); $stmt=$mysqli->prepare("SELECT COUNT(*) FROM `sessions` WHERE user_id=? AND ip=? AND user_agent=? AND hash=?"); $stmt->bind_param('ssss', $user_id, $_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT'], preg_replace('/[^0-9a-f]/', '', $_COOKIE['auth'])); $stmt->execute(); // и так далее
Во-первых, расширение mysql скоро будет deprecated в PHP, так что лучше сразу привыкать к mysqli.
Во-вторых, так оно само вам и экранирование сделает, и к указанному типу приведёт.
Кстати, IP адреса я бы хранил в целочисленных полях, оно так должно быть шустрее.porn
12.03.2017 17:16+2Оно уже deprecated и выпилено из PHP 7.
m0Ray
12.03.2017 17:18+1Не все ещё это заметили, ибо не все переехали на PHP7. Инерция-с.
Я же, как только услышал про deprecated, в своих велосипедах использую только mysqli.
Впрочем, велосипеды я нынче всё реже и реже делаю. Фреймворки рулят.porn
12.03.2017 17:21PDO
всё же удобнее: легко менять драйвер без внесения изменений в код.m0Ray
12.03.2017 17:27Чем-то удобнее, но запросы всё равно приходится писать на том диалекте SQL, который использует та или иная БД. А практически все нормальные фреймворки предоставляют свои уровни абстракции, которые вообще не требуют написания запросов. И тут уже нет разницы, PDO или специфический драйвер они используют.
А для велосипедов я редко использую что-то отличное от MySQL. Разве что SQLite, когда совсем уже лениво и велосипед из трёх строчек.
popov654
12.03.2017 17:47-1А зачем Вам вообще менять драйвер? Обычно БД выбирается один раз при старте проекта, и больше не меняется уже. Если вы, допустим, фрилансер — то и вовсе наверное одну и ту же предпочтёте использовать, ибо так проще. Соответственно, и драйвер будет один и тот же. Разве может быть драйвер быстрее и надёжнее нативного?
VolCh
12.03.2017 18:01+1Обычно БД выбирается один раз при старте проекта, и больше не меняется уже.
Обычно это работает если СУБД выбирается из принципа упрощения разработки, чтобы не морочиться с хранением и получением структурированных и не очень данных по принципу "без СУБД надо будет много кода писать, а эту СУБД я лучшего всего знаю". Если же СУБД выбирается по требованиям к проекту типа "обеспечить максимальную скорость записи с синхронной репликацией в дата-центры по всей Земле с соблюдением транзакционной целостности на любой момент времени", то проект может переезжать по нескольку раз с одной СУБД на другую в зависимости от того, какая здесь и сейчас показывает лучшие результаты (недавно показательный перевод поста про переезд Uber на MySQL был).
При одном условии это делается без особых проблем — код работы с базой максимально переносим, переезд не будет сравним по трудозатратам с написанием с нуля, а то и больше.
m0Ray
12.03.2017 18:02Неправда. Проект может впоследствие разворачиваться в разных окружениях, и БД тоже могут быть разными. Тот же Drupal может работать и с MySQL, и с PostreSQL, и даже с SQLite — для разных хостингов и нагрузок разные условия.
Если вы пишете на самом деле серьёзный проект, вы должны понимать, что рано или поздно вы можете упереться в вопросы производительности и какие-либо ограничения движка БД. Выходом может быть или полный переезд на другой движок, или разделение нагрузки между разными движками соответственно их плюсам и минусам. И что, переписывать весь код? В такой ситуации изначально написанный под PDO проект удастся адаптировать «малой кровью», а велосипед — ну вы сами понимаете.
И не просто так пишутся библиотеки ORM типа той же Doctrine.
И я бы не сказал, что PDO сильно медленнее нативного.popov654
12.03.2017 19:47-2ORM нужны больше для отделения данных от storage layer, то есть мы оперируем не запросами к базе, а объектами, а те сами себя получают и сохраняют (через ещё одну прослойку), если я правильно понимаю. Но это больше делается ради привычности кода (для тех, кто любит ООП) и ради общей красоты.
А переезд из-за того, что возможностей движка мало… Я не знаю. Наверное, должен быть реально гигантский проект, чтобы упереться в потолок того же MySQL. Плюс есть MariaDB, которая несколько производительнее, но работает с тем же API абсолютно. И потом, многое можно решить, взяв более мощное железо, либо докупив серверов. Это может оказаться сильно выгоднее, чем переписывать код.
И вообще, прелесть ORM я понимаю, прелесть PDO — вообще нет.
И что, переписывать весь код?
Таки да! Создать отдельную ветку и переписывать все вызовы к базе. Не весь проект конечно с нуля переписать, но процентов 30-40. Либо создать родительский абстрактный класс или интерфеййс, от него отнаследоваться, и старую реализацию оставить параллельно с новой. Вот поэтому и не надо такие переезды делать, себе дороже :)
И я бы не сказал, что PDO сильно медленнее нативного.
Ну чуть-чуть всё же медленнее должен быть. Он ведь обращается к базе не напрямую, а через ещё один драйвер по сути.
m0Ray
12.03.2017 20:08+1Это не для привычности кода, а для того, чтобы его было удобнее писать, поддерживать и переносить. Думать на уровне данных, решать, что куда определить и как обработать, а не о том, какое слово в SQL-запросе даст нужный результат и в каком, чёрт возьми, виде мне придут данные — объектом, ассоциативным массивом или вообще нумерованным. Для всех данных — единый интерфейс. А ООП он или процедурный — значения не имеет, хотя ORM подразумевает именно ООП.
Вообще-то, мы говорим MySQL, подразумеваем MariaDB. Дело просто в торговых марках.
Решать все вопросы докупкой серверов — вы меня извините, но над вами сейчас пол-интернета смеяться будет за такие заявочки. Грамотная оптимизация кода может ускорить работу в разы, что намного дешевле. Говнокод же, который будет грузить сервера непродуктивными запросами, не сумеет распределить нагрузку и будет блокировать свои же процессы, не спасут никакие облака и датацентры.
Прелесть PDO в том, что это и есть отчасти ORM, только низкоуровневый. В нём ещё нужно писать запросы на SQL, но уже не нужно думать о том, как обработать их результаты. Единообразный интерфейс к любому движку реляционной БД.
Процентов 30-40 — ну-ну. С использованием единообразных интерфейсов типа PDO надо будет в новой ветке лишь подкорректировать запросы, что опять же в разы, а то и на порядки снижает объём работы. С полноценным ORM вообще ничего не надо будет делать, только настроить соединение с БД. Практически все известные мне ORM-библиотеки используют PDO, ибо универсально.
Если сразу проектировать и писАть по-человечески, с соблюдением современных стандартов кода, то внесение изменений в логику работы, портирование и т.п. происходит очень гладко и быстро. Велосипеды же приходится перепиливать почти полностью, и обычно на стадии перепиливания проект загибается, ибо либо не устраивает потребителей, либо сами разработчики его бросают, ибо лень.
«Создать родительский абстрактный класс» — это первый шаг к ORM. Который удобно делать поверх PDO, потому что минимум различий между API драйверов БД.
akirsanov
12.03.2017 11:39+13авторизация -> аутентификация
в целом рановато вам еще рассуждать о безопасности, на данный момент статья — набор вредных советов из 1999 года.popov654
12.03.2017 11:40-7Ну почему вредных. Вредный совет — хранить пароли в плейнтексте, да ещё в файлах. Или полагаться исключительно на сессии (это советовали не в 1999-ом, а ещё в 2007-2008 во всех учебниках начального уровня).
akirsanov
12.03.2017 12:00+18Очень много бед в ИБ идет из-за непонимания. Непонимания механизмов, процессов, рисков. В вашем случае видна нехватка знаний в теме «безопасность веб приложений», есть перекос в сторону «кражи кук по вине дыры в безопасности браузера», но при этом приводите в примере sql инъекции. Это намекает на незнание темы и на неправильную оценку рисков по теме «безопасности веб приложений», на которую вы подвязались учить других. Чревато это тем, что часть людей(не берем в счет те приложения, где вы уже успели внедрить вышеприведенный код — там отдельные риски), которые точно также не понимают нюансов, стянут код у вас(просто нагуглят по запросу «Надёжная авторизация для веб-сервиса за один вечер») и влепят к себе. А достаточно было хотя бы просто не учить тому, в чем сами пока не являетесь специалистом.
popov654
12.03.2017 12:13-9Ну насчёт вышеуказанных замечаний — я уже внёс исправления. С User-Agent вообще спорно: туда точно никто в трезвом рассудке не станет пихать куски SQL-запросов. Тем более, не уверен, что даже инъекция в этом случае даст возможность взломщику прочитать структуру БД (только убить там все данные, но это не так интересно коммерчески).
Наконец, я рассуждал про безопасность на уровне браузера. Не все браузеры дают менять юзер-агент, а те, что дают — там надо ещё найти, где это делается. Всё же такой код безопаснее стандартного варианта. Не забывайте, что взломщик не знает исходников.akirsanov
12.03.2017 12:35+11Ну вот про это и речь — вы просто не понимаете риски и опасность того, что вы пишите. «С User-Agent вообще спорно». Для вас подмена юзерагента без исходного кода приложения — нечто из рамок выходящее, маловероятное и все такое. Вы по другую сторону барьера, вы не знаете техник атакующего. Для пентестера(и всяких взломщиков в том числе) — один из базовых подходов при backbox тестировании. Просто вот так при анализе веб приложения пентестеры практически сразу же берут да и втыкают кавычки в юзерагент, не пользуясь для этого браузером, а например Burp Suit'ом или Fiddler'ом. Просто так все сканнеры, начиная с Acunetix'a делают тоже самое в автоматическом режиме. Такая уязвимость найдется любым адекватным сканнером уязвимостей.
popov654
12.03.2017 14:37-6Спасибо, не знал. Знал про всякие атаки виде "Slow query", под это даже Antiloris mode был под Apache… Знал про всякие трюки с хитрым экранированием символов в URL… Про User-Agent не знал, каюсь.
d-stream
12.03.2017 14:13+4Это было в волшебнике изумрудного города. Сюжет с очень прочными воротами… но в чистом поле…
popov654
12.03.2017 12:23-6А в чём разница этих терминов, не поясните? Я встречал термин «авторизация» очень часто именно в том значении, в котором он применён у меня.
VolCh
12.03.2017 13:11+4Идентификация — представление пользователя, "я — такой-то" (юзернейм в форме логина)
Аутентификация — доказательство личности идентифицированного пользователя, "и вот секрет, который знаю только я" (пароль в форме логина)
Авторизация — проверка прав пользователя на осуществление конкретного действия, "мы верим, что вы "юзернейм", но вы не имеет права на действия, которое пытаетесь совершить" (бан по юзернейму или невозможность редактировать комментарии никем кроме автора и админов)
Это если "на пальцах".
popov654
12.03.2017 14:45-3Спасибо, но это уж очень дотошно… Зачем разбивать действие по заполнению простой формы из двух полей на два разных понятия? Насчёт авторизации — я прекрасно знаком и с этим значением термина, да. Проверка прав доступа, уровни, привилегии) Но это из другой области совсем.
Смотрите, форму, куда вы вбиваете пароль — в веб всё время называют формой авторизации. Никто не называет её "формой аутентификации", я по крайней мере такого не слышал.
VolCh
12.03.2017 16:20+1Как правило, обработка такой формы это именно 3 этапа, авторизация, проверка прав — последний. И она из той же оперы, собственно только ради неё и нужны часто первые два, особенно второй.
nmk2002
13.03.2017 12:07+1Тут нет противоречия. Когда вы нажимаете на кнопку «войти» в «форме авторизации», то происходит:
1. Идентификация вас по имени пользователя, которое вы ввели в поле «логин»
2. Аутентификация — проверка, правильный ли пароль был введен в поле «пароль»
3. Авторизация — предоставление доступа в соответствии с вашими правами.
Все логично, так как с точки зрения пользователя он в итоге авторизуется на сервисе для доступа к своим ресурсам. Не писать же теперь «форма идентификации, аутентификации и авторизации», ведь аутентификация и идентификация это в данном случае просто компоненты необходимые для авторизации.
Давайте на хабре будем использовать термины правильно.
vvsvic
12.03.2017 12:15+3Вы зря используете IP адрес клиента:
1. Многие сидят за NAT.
2. Некоторые провайдеры используют короткие сессии, выделяя каждый раз новый IP клиенту.
3. У клиента может быть несколько провайдеров с балансировкой траффика.popov654
12.03.2017 12:18-3Абсолютно согласен. Именно поэтому привязка к IP в этой схеме сделана таким образом, как сделана, а не на полную. Вы бы сделали иначе?)
Насчёт пункта 3 — не встречал, и даже не очень знаю, как такое реализовать, а 1 и 2 сплошь и рядом, да.
Но надо всё-таки понимать, что я не уникальность клиента по IP определяю. ВК ведь тоже IP берёт в расчёт, и при заходе откуда-нибудь из-за границы просит подтвердить номер телефона (раньше просил капчу ввести). Только вчера на эту особенность наткнулся при смене хостинга на заграничный, токен перестал работать, пришлось проходить валидацию.d-stream
12.03.2017 14:17Насчёт пункта 3 — не встречал, и даже не очень знаю, как такое реализовать
методов — десятки. Обобщенно — load balancing.
Да и даже проще: какой-нибудь человек со смартфоном, гуляющей по квартире — может легко метаться между домашней wifi сетью через наземного провайдера и интернетом опсоса — как минимум метания между двумя разными адресами.popov654
12.03.2017 15:57-1Ну так моя система отлично такой сценарий обрабатывает. Редирект-то почти мгновенный, о чём и речь. В вк это всё происходит существенно дольше (но у них и нагрузка совсем не того масштаба, тут наивно сравнивать).
porn
12.03.2017 12:26+3Очень вредная статья. Доверять заголовкам HTTP нельзя — это в любом учебнике написано.
mysql_query
— вы серьёзно? Почитайте на досуге.popov654
12.03.2017 12:28-4Вредная в чём? Похоже на субъективные придирки. Да, инъекции — зло, но в статье речь не про работу с MySQL была, и не про обработку входных данных.
Суть-то вообще не в этом. А как сделать авторизацию, работающую по лучшим принципам, так сказать. С ведением логов заходов, возможностью «прибивать» сессии на разных устройствах, и прочее.
А что с mysql_query не так? Стандартная функция для запроса к mysql, вроде как.porn
12.03.2017 12:37+1Новички, прочитав в заголовке «Надёжная...» могут подумать, что здесь описаны сорт оф лучшие практики, а это не так. Логгирование — это отдельная тема, она может и должна рассматриваться вне рамок авторизации/аутентификации. С
mysql_query
очень не так, хотя бы потому чтоWarning This extension was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0. Instead, the MySQLi or PDO_MySQL extension should be used.
popov654
12.03.2017 12:40-4Ну так предложите практику лучше, я же совсем не против. Как же принцип «отрицаешь — предлагай»? MySQLi может и лучше, я в этом и правда не очень силён, но текст, опять же, не об этом. «Deprecated in 5.5» — совершенно не помеха, когда по функциям за глаза хватает версий 5.3 — 5.4. Но даже в 5.6 расширение mysql работает, к слову, если подключить.
d-stream
12.03.2017 14:19+2Предложение может быть таким: убить терапевта, рекомендующего садится на огурцы и выписывающего рецепты на лошадиные дозы фуфломицина -)
popov654
12.03.2017 14:48-3Так а в чём огурцы-то? Вот вы говорите, в таком-то фреймворке/CMS реализовано лучше. Так расскажите, в каком, и чем именно лучше, давайте обсудим. Надо позицию ведь хоть немного аргументировать.
И я не очень уверен, что все минусующие самостоятельно за вечер написали бы более грамотную реализацию (не глядя в сторонний код).
d-stream
12.03.2017 14:53+1Огурцы в том, что предложенная и заявленная «панацея» оказалась не то чтобы ненадежной, а просто дырявой.
Все. На этом уже надо ставить точку.
Кстати половина минусующих может быть вообще не программисты, а специалисты по безопасности, которые не пишут код -)popov654
12.03.2017 15:00-2А в чём дыры-то? Отсутствие вызова mysql_real_escape_string в паре мест (учитывая, что это просто не пришло в голову, о другом были мысли при разработке)? Ну это уже слишком толсто, ребят. Не про это ведь текст. Или вообще никто не читает, а только комменты почитать заходят?
d-stream
12.03.2017 15:02+1Дык в чем проблемы с лечением огурцами по Малахову? Если это совместить с занятиями спортом, прививками и лекарственной терапией — тож будет эффект =)
popov654
12.03.2017 15:10-2Потому что огурцы вредны. А данный код, если без инъекций — вроде как не особо… Хотя может, я ещё чего-то не учитываю)
d-stream
12.03.2017 15:18+1Дык огурцы, если их кушать — полезнее чипсов даже.
А так — да, первое — инъекции, второе — привязка к ip
В итоге шикарная яичница, только яйца просрочены и масло прогорклое…
Хотя про огурцы я конечно погорячился, они стоят на втором месте после воды по причине смертности… ведь все умершие хоть раз но ели огурцы…popov654
12.03.2017 15:24-1А с привязкой что плохого? Она с одной стороны позволяет сработать как некоторый триггер ("айпи поменялся — значит, что-то изменилось, повод перепройти авторизацию/аутентификацию"). Но при этом это не принуждает вручную заполнять заново форму.
Вы никогда не замечали, что если взять телефон с открытым в браузере вк, выйти из дома, отключившись от вайфай, пройтись по улице, а потом обновить страницу — то у вас будет 1-2 редиректа с передачей в GET-параметре какого-то хэш-кода? И не говорите после этого, что там нет привязки по IP. Ещё как есть :)
porn
12.03.2017 15:03+1Если б использовали
\PDO
, то к вашему коду на порядок меньше придирались.popov654
12.03.2017 15:19-3Я почитал специально про PDO. Про синтаксис со знаками вопроса, как в JDBC на Java (в Android и Spring, к примеру). Знакомо. Но как по мне, удобства это не прибавляет.
Пишут, что там автоматически производится экранирование, и таким образом защита от инъекций идёт из коробки… Согласен, так проще, чем каждый раз вручную. Зато вручную контроля больше. Можно более жёсткие преобразования делать над входными данными, чем просто экранирование.
Нет, никто не мешает совместить это с PDO, но производительность чуть просядет, если преобразование делать дважды для каждого аргумента.
Ну и на самом деле, меня просто так учили. В хорошем учебнике от Bhv-Петербург по PHP5, который ещё 2005 года издания, вроде (я его читал в 2006-2007) использовалось только mysql расширение. И оно мне очень нравится своей простотой и интуитивностью, чего уж там.
К слову, я долго гуглил, и не нашёл серьёзных "дыр" в нём, разве что менее богатый функционал и отсутствие новых функций вроде поддержки транзакций. Но там для начала движок СУБД должен поддерживать транзакции (не любой поддерживает!), а если он их поддерживает — можно их и через mysql_query точно так же инициировать, выполнять какие-то запросы, и завершать.
Также есть такой момент, что mysqli умеет работать с хранимыми процедурами. В принципе, я понимаю, что имеется в виду — чтобы сразу иметь возможность получать результат в переменную. Но мне на практике хватало создать хранимую процедуру через phpMyAdmin, вызвать её в нужных местах в самих SQL-запросах, и получить уже готовый результат. То есть это тоже как бы не то, без чего нельзя жить :)
porn
12.03.2017 15:32+1Вообще, рекомендую ознакомиться с PHP: The Right Way.
popov654
12.03.2017 16:03-1Спасибо, интересный сайт. Но там опять про 7.1, прямо начиная с главной :) Нет у вас каких-нибудь Best Practices под PHP 5.3-5.4?
Но всё равно почитаю. Интересно же, что рекомендуют в качестве советов и правил хорошего стиля.
porn
12.03.2017 16:15+2Большинство описанных практик подходит и для >=5.3, только зачем использовать 5.*, когда есть 7.1?
popov654
12.03.2017 16:24-3Не люблю, когда меня к чему-то принуждает разработчик платформы. И только. Так ничего против семёрки не имею.
Это знаете, как с NetBeans. Вот стоит у меня версия 6.8, всем она нравится… Но нет под неё расширений. Ни для CodeIgniter (вообще), ни под новый клиент SVN (а старый не поддерживается серверами, небезопасным считается). И приходится либо ставить что-то новее, либо без поддержки SVN сидеть. А казалось бы, что стоило авторам разрешить установку новой версии модуля (всё равно API небось не поменялся существенно) на старую версию IDE.
porn
12.03.2017 16:27+1Попробуйте PhpStorm (если по EAP — бесплатно). Попробуйте GIT. Если хотите SVN — был когда-то инструмент TortoiseSVN — не знаю как он сейчас поживает, либо юзайте CLI для SVN.
popov654
12.03.2017 16:35-2У меня стоит TortoiseSVN, к счастью, версия 1.7 на моей ОС поддерживается ещё. Но хочется-то сразу из IDE чтобы было)) К хорошему быстро привыкаешь. Хотя конечно это всё ерунда, можно без проблем работать и в 7.х, или какие уже там, может и восьмые.
Просто меня в момент выхода 7.0 добили две вещи: огромное количество варнингов к моему Java коду, которые я понятия не имел, как исправить, чтобы их стало хотя бы на треть меньше, и то, что они полностью убили встроенный Javadoc. Все имена переменных в выпадающих элементах справки поменялись на i1, i2, i3… Помучился неделю и снёс. Возможно, к версии так 7.4 это и исправили. Но вообще-то такое сразу в идеале должно работать. Не RC ведь ставил, релиз нормальный.
porn
12.03.2017 16:39+3Если IDE кидает вам варнинги — обычно это говорит о том, что у вас что-то не то с кодом. Лучше бы вам всё же попытаться разобраться с проблемными местами.
popov654
12.03.2017 21:05-1Ну когда их было в прошлой версии 0, а стало over 80 штук (на файл, где около 1500 строк кода) — это не нормально… И я честно пытался рефакторить код. Избавился от силы штук от 4-5.
Тем более, это не варнинг в стиле "всё плохо, красная иконка", это предупреждения о нарушении некоего стайлгайда в области композиции классов. И они там были буквально на каждый чих.
Код не был кстати настолько ужасен, это была курсовая. Будь там всё плохо — мне бы препод раньше вставил за это :)
popov654
12.03.2017 15:20-1Насчёт движков — InnoDB поддерживает, MyISAM, вроде как, нет (раньше точно не умел).
Ernado
12.03.2017 22:20+1все минусующие самостоятельно за вечер написали бы более грамотную реализацию
Штука в том, что писать собственный механизм авторизации "за один вечер" в принципе не стоит. Гораздо правильнее использовать проверенные решения (например, входящие в состав используемого фреймворка) и не писать велосипеды.
lair
12.03.2017 23:53+3И я не очень уверен, что все минусующие самостоятельно за вечер написали бы более грамотную реализацию (не глядя в сторонний код).
Я бы не написал. Но я бы и не взялся. Зачем, если уже есть работающие готовые решения?
symbios_zi
12.03.2017 12:33+4Есть ощущение что статья опоздала лет на 10. MySQL PDO уже давно пора освоить. Я это к тому что mysql_result() в php7 работать не будет.
popov654
12.03.2017 12:34-7Да, не будет. А зачем именно семёрка? Я до сих пор на всех серверах благополучно 5.3 использую.
Есть ещё правда mysqli, но лично мне с этим интерфейсом менее удобно работать. Хотя говорят, он лучше. Возможно, дело привычки просто.porn
12.03.2017 12:40+6Я до сих пор на всех серверах благополучно 5.3 использую.
Сегодня можно благополучно пользоваться бричками, как транспортом, но почему-то людям больше нравятся автомобили.popov654
12.03.2017 12:42-4А кроме шуток? Что за редкий функционал такой, ради которого стоит менять версию? Не, ну ладно там 5.2, там со сборкой мусора похуже, с производительностью, md5 хэш короче намного (по дефолту 16 символов вроде). Но 5.3 чем не вариант?
porn
12.03.2017 12:49+4Достаточно посмотреть руководство по миграции и, например, статьи на хабре и других ресурсах, бенчмарки (1, 2, тысячи их), чтобы пришла уверенность, что обновиться стоит.
popov654
12.03.2017 12:55-1Спасибо, обязательно почитаю. Люблю статьи в таком формате.
Насчёт бенчмарков — вы уверены, что эти цифры получены не только за счёт оптимизаций в ООП и скалярного тайпхинтинга? Просто не очень верится, что всё остальное можно было ускорить, а не сделать медленнее, тем более, что внутренней кодировкой вроде как стал двухбайтовый юникод (а раньше однобайтовая была). Хотя возможно, это ещё с версии 5.6, я не помню, увы...
И была даже статья на Хабре про то, что "PHP6 не будет", там писали, что у авторов возникли огромные проблемы со скоростью при попытке перевести все строковые функции на работу с двухбайтовой кодировкой. В итоге оставили всё как есть, а чуть оптимизированную версию выпустили как 5.5.
porn
12.03.2017 13:03Тайпхинтинг, кстати, даже замедляет работу, а не ускоряет её. Насколько я понимаю, его ввели скорее для удобства разработки и отладки. О том, какие улучшения были сделаны, есть статьи, слайды и видео, в котором Дмитрий Стогов рассказывает подробно.
popov654
12.03.2017 14:49Тайпхинтинг, ИМХО, должен ускорять процесс. Потому что он позволяет заранее рассчитать необходимые объёмы памяти под данные, и избавиться от кучи динамических проверок (которые неизбежны, когда переменная часто меняет тип). Опять же, где-то читал в авторитетном источнике, что это даёт большой прирост в скорости :)
porn
12.03.2017 14:52+1На SO есть довольно развёрнутый ответ.
tl;dr:Today, the use of scalar and strict types in PHP7 does not enhance performance.
popov654
12.03.2017 15:09Because scalar type hints guarantee that a passed argument will be of a certain type within a function body (at least initially), this could be used in the Zend Engine for optimisations. For example, if a function takes two float-hinted arguments and does arithmetic with them, there is no need for the arithmetic operators to check the types of their operands.
In previous version of php there was no way to know what kind of parameter could be passed to a function, which makes really hard to have JIT compilation approach to achieve superior performance, like facebook's HHVM do.
@ircmaxell in his blog mentions the possibility of bringing all this to the next level with native compilation, which would be even better than JIT.Последний абзац особенно здесь интересен. Если сделать компиляцию в нативный код (в strict mode-то кто мешает, хотя бы на уровне отдельных функций), то будет очень быстро. То есть как раз речь о том, чтобы скомпилировать один раз, и использовать постоянно.
porn
12.03.2017 15:11Над JIT сейчас Дмитрий Стогов работает, емнип. Это будет, скорее всего, в восьмой версии. У нас речь о седьмой.
VolCh
12.03.2017 13:19Как минимум со времён 5.3 оптимизировали работу с массивами, если не трогать ООП.
VolCh
12.03.2017 13:27В итоге оставили всё как есть, а чуть оптимизированную версию выпустили как 5.5.
В этом отношении и в 7 оставили всё как есть и пока планов по изменению не будет.
А вообще проект на Symfony 1 с минимальными правками самого фреймворка на 7.0 стал показывать процентов на 30 меньшее время генерации ответа по сложным запросам и процентов на 70 меньшее потребление памяти по сравнению с 5.3.
popov654
12.03.2017 14:52-2Так вы не сравнивайте Symfony (один из самых тяжёлых фреймворков) с легковесными проектами, где PHP только выборку из БД делает да результаты в виде JSON возвращает (ну максимум — какой-то HTML генерирует для выдачи в браузер). Там не так всё медленно, чтобы видеть прирост, мне кажется. Про массивы выше уже мне написали — но это только на очень большом числе итераций можно заметить, на малых объёмах сильно роли не сыграет.
popov654
12.03.2017 13:03-1На самом деле, на очень маленьких проектах, и если хостинг не очень слабый, разницы можно не ощутить. У меня была даже совсем странная история, когда на простом веб-приложении (в рамках одного веб-хостинга с возможностью переключать версии) 5.3 работал быстрее чем 5.4, а 5.2 ещё быстрее, чем 5.3. И в целом, это может даже быть объяснимо: меньше функций, меньше синтаксических возможностей — меньше потребление RAM, где-то быстрее интерпретация. Хотя может, я и не прав. Трудно сказать.
Между 5.4 и 5.6 я тоже разницу ощущаю с трудом (хотя 5.6 вроде как побыстрее, но может, это эффект плацебо в действии такой).
VolCh
12.03.2017 13:17+5Я до сих пор на всех серверах благополучно 5.3 использую.
Вы это серьёзно? Статья по безопасности с целевой версией языка, поддержка которой полностью, включая закрытие уязвимостей, прекращена 2,5 года назад? Даже для 5.6 активная поддержка прекращена уже, только уязвимости будут закрывать ещё какое-то время.
popov654
12.03.2017 15:38-2Конечно, серьёзно. Статья не по безопасности вообще, а с идеей, как немного улучшить стандартную базовую авторизацию, которую предлагают в простых учебниках начинающим.
Какая разница, какая версия? Если использовать общий и простой стиль написания кода, то код одинаково будет работать на любой версии (и везде без ошибок и предупреждений). Ну кроме расширения mysql, тут да, проблема.
eshimischi
12.03.2017 13:23А зачем вы тогда вообще пишите свои поделки на php? Затем и 7ка, что пора себя переучивать пользоваться composer, разобраться в неймспейсинге, psr и для авторизации/логина на сайте использовать готовые, безопасные приемы и рабочие проекты людей. Дело тут не в скорости работы интерпретатора языка, сколько в особенностях самого языка. Отступать на 2 шага назад каждый раз и не пробовать «новые» аспекты — это от слова худо — программист.
popov654
12.03.2017 15:45-4А что такое composer и зачем он вообще?)
Это не поделки, а вполне реально работающие проекты, между прочим. Этот модуль довольно простой, но даже в нём была применена пара оригинальных фишек (пароль в открытом виде не хранится нигде, файл security инклюдится во все разделы как второй механизм проверки в придачу к обычной проверке $_SESSION['user_id']). У меня есть разработки существенно сложнее, естественно. Просто решил поделиться вот этой, подумал, кому-то будет интересно… Может, я ошибся, и это тривиально для всех.
готовые, безопасные приемы
В чём они безопаснее? Использование готового — обычно отупляет и отучает думать и писать код самостоятельно. А то да, встречал уже одного товарища, который библиотеку для авторизации на гитхабе нагуглил, вместо того, чтобы написать самому за пару часов.
и не пробовать «новые» аспекты
Не, попробовать-то можно, ради интереса. Только не надо всех обращать в свою религию, и убеждать, что эти аспекты жизненно важны и необходимы)
oxidmod
12.03.2017 20:46Инклюдить в каждом файле — вот это тупость.
popov654
12.03.2017 21:23Извините, почему же? А импорт пакетов в Java в начале файла класса — не тупость? А объявление неймспейса в C++? Не будьте так категоричны. Это всего одна строка, а файлов, куда надо её добавить (и больше не убирать) — штук 5-6. Прямо так сложно, Боже мой.
m0Ray
12.03.2017 21:44+1Когда это касается безопасности, и когда вы её забудете добавить куда надо — будет новая дырка.
popov654
15.03.2017 17:31Не забуду, если таких мест всего 2-3 на весь проект(в каждом кабинете, грубо говоря). Кроме того, при создании нового проекта обычно весь этот код банально копируется из старого. Тут разве что если стереть случайно. Но в этом плане с чем угодно можно напортачить, если думать о постороннем :)
oxidmod
13.03.2017 08:33А вы почитайте чем инклюд отличается от импорта. Может тогда дойдет
popov654
15.03.2017 17:26-1Абсолютно ничем.
Если вы про многократный инклюд одного и того же — require_once() есть на этот случай. Ну и при грамотной архитектуре все инклюды идут в главном модуле, а не где попадя.lair
15.03.2017 17:36+1Абсолютно ничем.
То есть тот малозначительный факт, что одно выполняет код, а другое — нет, вас не смущает?
popov654
16.03.2017 05:01Иногда такое выполнение бывает очень удобно. Смотрите это как на вызов внешней процедуры с глобальными параметрами.
Вот нужно мне кусок шаблона вставить (календарь вывести или виджет какой-то). Что проще всего для этого использовать? Конечно, require или include. И уже там писать макароны, а не засорять основной файл-"каркас".
lair
16.03.2017 11:45Иногда такое выполнение бывает очень удобно.
Никто и не спорит с тем, что удобно. Спорят с тем, что include и import — разные вещи.
Смотрите это как на вызов внешней процедуры с глобальными параметрами.
Ну то есть как на абсолютное зло?
Вот нужно мне кусок шаблона вставить (календарь вывести или виджет какой-то). Что проще всего для этого использовать? Конечно, require или include.
Проще — возможно (вам). Правильнее? Далеко не факт, я всегда предпочту явный вызов кода.
Собственно, с этого же все и начиналось — правильно ли подключать проверку безопасности через
include
. Нет, неправильно — потому что можно забыть сделатьinclude
и кусок останется незащищенным. Правильно ли подключать черезimport
и вызов кода? Да тоже не очень, потому что можно забыть вызов.
Правильно взять фреймворк, который позволяет подключать промежуточные обработчики на каждый вызов безотносительно того, что там написано в файле, и включить механизмы безопасности в него.
SerafimArts
15.03.2017 19:23При грамотной архитектуре (да и вообще в любом проекте в 2017ом году) инклуд только один на весь проект —
require '... autoload.php';
— остальное декларативные методы ссылок на нужные вендорные (и не только) либы.VolCh
15.03.2017 19:59Автозагрузку функций пока ещё не сделали.
SerafimArts
16.03.2017 00:11+1И что? Вы документацию композера пропустили, где для этого есть специально прописанная секция files? ;)
Прошу заметить, что в проекте как был, так и остаётся один единственный require. Моих слов это не отменяет.
popov654
16.03.2017 05:07Я где-то в документации читал, что использование автозагрузки через регистрацию функции-автозагрузчика может давать сильные тормоза по сравнению с её неиспользованием. Вы не могли бы прокомментировать как-то этот момент?
И потом, вы сейчас говорите про проект, написанный в объектном стиле. Если это не так, зачем нам autoload?
Просто я бы не согласился, что проект, не использующий ООП — сразу с порога проект с плохой архитектурой. Смотря как сделано...
SerafimArts
16.03.2017 05:51Вы не могли бы прокомментировать как-то этот момент?
Нет, десятитысячные доли секунд на виртуалках за 100 рублей\мес меня мало волнуют =)
И потом, вы сейчас говорите про проект, написанный в объектном стиле. Если это не так, зачем нам autoload?
А зачем писать как-то иначе и жрать кактусы? Есть инструмент — используйте, если инструмент не достаточно удобен, значит он не для этого.
Просто я бы не согласился, что проект, не использующий ООП — сразу с порога проект с плохой архитектурой. Смотря как сделано...
Я бы посмотрел на проекты с более чем 20ю метрами исходного кода в процедурном стиле, а ещё такой грамотный по архитектуре… Примеров не найдёте? Ну таких, чтобы сразу в помойку не выкидывать, а чуть-чуть повосхищаться дерзостью автора.
ООП, хоть и критикуемый, но по праву заслужил свои позиции. Действительно крупные проекты, ну или чуть круче лендингов при других подходах слабореализуемы.
Free_ze
13.03.2017 17:28А импорт пакетов в Java в начале файла класса — не тупость? А объявление неймспейса в C++?
Там такую необходимость даже специально проигнорировать не получится — компилятор/линковщик напомнит.
avost
12.03.2017 23:32А то да, встречал уже одного товарища, который библиотеку для авторизации на гитхабе нагуглил, вместо того, чтобы написать самому за пару часов
Ну, вот вы написали, а толку? Дыра на дыре сидит и дырой погоняет. Причём вы ещё и принципиально отказываетесь понимать что вам говорят. Ваш товарищ поступил гораздо мудрее.
m0Ray
12.03.2017 23:47Надо на разные параметры найденного готового решения внимание обращать. Вот топикстартер ведь тоже мог выложить своё поделие на гитхаб, а кто-нибудь и скачал бы…
Если тот товарищ не просто слямзил первое попавшееся решение, а потратил хотя бы пять минут на поиск возможных или существующих проблем с найденным решением — выигрыш очевиден: пять минут против двух часов.
brevis
12.03.2017 12:45+4Тенденция прямо: людям с фамилией Попов в IT не всегда везет :)
(это добрая шутка если что)popov654
12.03.2017 12:49-2Зато есть очень талантливый мой полный тёзка, который неплохие видеоуроки по вебдизайну выпускает. Кто-то из моих знакомых очень хвалил его :)
А тот Попов — ну там да, что поделать. Бывает)
eshimischi
12.03.2017 13:28+3Возьмите и разберитесь в любом из данных проектов slim-basic-auth, slim-auth, slim-jwt-auth, slim-token-authentication. Даже на примере фреймворка Slim, вы взглянете на свой кусок кода как на нечто… неприемлемое для современного Веб.
popov654
12.03.2017 14:55-3К чему в вашем предложении слово "современного"? Как будто понятие безопасности и устойчивости к разным угрозам зависит от времени.
Код посмотрю, спасибо. Пока из описания понял, что это некая надстройка над модулями Zend… В котором уже и так есть что-то для аутентификации.
eshimischi
12.03.2017 15:47На одном из западных форумом, посвященных безопасности в Веб, сказано очень лаконично и просто «не пытайтесь создавать безопасность своими руками, используйте рекомендованные решения, созданные специалистами по безопасности». Я использовал слово «современного» в контексте даже информации о рекомендациях не использовать md5 для кодирования парольной информации, а использовать более стойкие и новые криптографические методы.
popov654
12.03.2017 16:13-2Я не сам это придумал. Функция md5 используется, например, в CMS Joomla 1.5 для хранения хэшей паролей (собственно, сам формат хранения и идею делать равными по длине соль и хэш я взял оттуда в своё время). Более того, в другой CMS (не очень популярной, типа Street CMS) я видел ещё менее стойкое шифрование — там очень короткие на вид были строки.
eshimischi
12.03.2017 16:16То что там испоьзуется — не значит что это правильно…
Выдержка с php.com:
«Why are common hashing functions such as md5() and sha1() unsuitable for passwords?
Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be very fast and efficient. With modern techniques and computer equipment, it has become trivial to „brute force“ the output of these algorithms, in order to determine the original input.
Because of how quickly a modern computer can „reverse“ these hashing algorithms, many security professionals strongly suggest against their use for password hashing.»popov654
12.03.2017 17:30-2Я читал опять же статьи на эту тему, — какой нужен объём диска, сколько памяти, и сколько процессорного времени для подбора хэшей MD5. Выходило довольно много. Под 300-450 Gb радужных таблиц на диске (тогда как 500-гигабайтный USB жёсткий диск стоил довольно прилично, хоть и не заоблачно, и не каждый мог позволить его пустить на такое даже при большом желании), плюс существенное время, исчисляемое сутками. И то там рассматривалось вскрытие хэшей, полученных без соли, и вроде даже частично содержащих слова.
Так что мне кажется, авторы слегка перестраховываются (как и все специалисты по криптографии), играя на опережение, и предупреждая всех заранее, чтобы потом всех не застало врасплох.
MikailBag
12.03.2017 20:05<cap-mode>Ну, 450 Гб довольно мало.
За несколько тысяч рублей можно HDD на 2000 Гб купить.</cap-mode>popov654
12.03.2017 21:28-1Ну, в 2009-ом это стоило несколько дороже (когда я ту статью смотрел). Хотя тоже было конечно же вполне реально :)
Но вот году ещё в 2008-ом в самом начале, когда родители этот Seagate покупали — там полутерабайтные внешние накопители стоили прилично. Тысяч 8-10 минимум.
То есть это надо было выкинуть 8-9к, чтобы с некоторой вероятностью что-то подобрать (а скорее, ничего не подобрать). Плюс скорость доступа у этих винтов была сильно не очень.
porn
12.03.2017 16:16+3Joomla — это явно не тот проект, с которого нужно брать пример.
popov654
15.03.2017 20:12А аргументировать как-то это слабо? :)
Особенно учитывая, что там всё в лучших традициях ООП сделано.porn
15.03.2017 20:27Не хочу тратить на это время.
там всё в лучших традициях ООП сделано
Смешно.popov654
16.03.2017 05:12А что смешного, если это так? Есть CMS-ки, сделанные и в процедурном стиле как бы.
Не хотите — ваше право, но я так понял, у вас просто весомых аргументов нет. А это как бы один из лидеров на рынке бесплатных CMS. Наравне с Wordpress и Drupalkruslan
18.03.2017 01:34+1Вы шутите?!!! На моей памяти — джумла самая дырявая, не говоря о коде (про это я писал выше).
SerafimArts
18.03.2017 03:41-1Да, ладно, по сравнению с вордпрессом и битриксом — на джумлу можно молиться =)
popov654
12.03.2017 15:29Я посмотрел код по первой ссылке (по первым двум, у вас там одинаковая вставилась). Лаконично, абстрактно, но не очень понятно, что же там на самом деле происходит. Это очень высокоуровневый код, он сильно на код Zend опирается. Вы и код Zend мне почитать предлагаете?)
eshimischi
12.03.2017 15:58Документацию не нужно читать, в первом случае используются компоненты из билиотеки Zend, адаптированы под использование в фреймворке Slim. Дважды вставил верно slim-basic-auth. Там нет никаких прямых обращений к БД — эта практика сама по себе небезопасна. Вам выше уже указали на места, которые могут быть подвергнуты sql-инъекциям и вещам пострашнее.
popov654
12.03.2017 16:08Но БД существенно производительнее файловой системы (попробуйте запустить 2-3 скрипта на longpoll от одного юзера и попытаться в цикле подёргать сессию, будет не очень здорово). Насчёт инъекций — есть функции экранирования, есть PDO, как сказали выше, есть здравый смысл наконец. Не вижу никаких причин её не использовать. Более того, можно создать свой обработчик PHP сессий, который будет сохранять их в БД, а не в файлах, в языке предусмотрели даже такую возможность. Вот здесь об этом упоминается: http://www.php.su/articles/?cat=protocols&page=009
porn
12.03.2017 16:22Сессии вы можете хранить где угодно: хоть в файлах, хоть в in-memory, хоть в MySQL — где угодно. Удобно, кстати, добавить уровень абстракции «хранилище сессии», механизму аутентификации должно быть пофиг где эта сессия хранится. Вас критикуют за то, что вы небезопасно реализовали.
popov654
12.03.2017 16:30Вот мне правда интересно узнать, как реализовать безопасно, я же не троллинга ради спрашиваю.
Если в БД хранить можно — то из недостатков остаётся только низкий уровень абстракции и привязка к деталям реализации. Код можно сделать красивее и разнести его на несколько уровней абстракции, хотя его станет побольше. Но это к вопросу о красивой архитектуре, а не о безопасности :)porn
12.03.2017 16:36А про реализацию в интернете достаточно материала. Читайте-изучайте.
popov654
12.03.2017 16:56Нет, я имею в виду, что в текущем варианте не ок. Ну код там не красивый в самом скрипте аутентификации — это понятно, я как бы не старался его делать хорошим. А с остальным всё ведь хорошо?
Опять же, хочу напомнить, что общую идею хранения идентификационных данных в сессии придумал не я. Это в каждой первой статье делать предлагают. Да и в CMS по-моему так же сделано, например в той же Joomla, откуда я брал формат хранения паролей.
Вообще способов-то не так много: нам нужен клиентский контейнер, транспорт и серверный контейнер. Клиентский контейнер — очевидно, cookie (их проще всего выставить с сервера).
Транспорты рассматриваются по ссылке в статье, которую я приводил в комментарии выше. Обычно, опять же, используют cookies, поскольку они очень редко отключены у пользователей, и при этом не нужно городить параметров в адресной строке и виртуальных каталогов.
Остаётся серверный контейнер — по дефолту для сессий в PHP это файлы. Я, по сути, реализовал свой независимый контейнер хранения (можно считать это велосипедом, конечно), который работает совместно со стандартным, основан не на файлах а на MySQL, и хранит немного другие вещи.
При этом кука с хэшом ставится сервером при аутентификации (и шифруется им же), а затем передаётся клиентом с каждым запросом. И специальным модулем проверяется на корректность (как признак валидности клиента, она ведь получена из пароля). Вроде всё нормально сделано.
kruslan
12.03.2017 18:14+2На самом деле, всё ужасно от слова «совсем».
1. md5. даже не sha1. при том, что давным-давно практически во всех уголках инета рекомендуются спец.функции. Раньше был crypt, сейчас очень рекомендуется использовать password_*.
2. mysql. ну про это выше неоднократно написали.
3. sql-inj. тоже написали.
4. хранение пароля в сесии (не важно, php- или своей). Что-за бред? Почему в базе храним хешированный пароль, а в сесии нет? Храним хешированный с другой солью + подпись для проверки целостности данных. Эти 2 простых приема дадут больше пользы, чем весь код в посте.
5. Привязка к ip — это жесть. Вы часто приводите в пример vk, но я уверен, что там это реализовано иначе — проверям, сменилась-ли страна/регион/город с момента последнего обращения, а не смену ip. Не должна аутентификация быть привязана к чему-то, кроме самого пользователя.
6. Никогда(!) и никому(!) не говорите ничего про джумлу. Хуже кода, лично я, не видел ни разу.
И да, хотите сделать что-то правильно — хотя-бы(!) изучите то, что сделали и проверили в работе другие люди.
P.S.: отдельная жесть — php 5.3, svn. Тут даже не знаю что сказать…popov654
12.03.2017 20:38Не знаю, UnitPay (платёжка, с которой мы год работали) только полгода как от md5 в пользу sha1 отказался. Там это используется для получения контрольной подписи. Принципиально есть какие-то аргументы, почему md5 не есть гуд? Ещё раз, я читал анализ, за вменяемые сроки там ничего не получить. А то, что получить — обычно это то, что УЖЕ когда-то было скомпрометировано, и теперь просто мы детектируем, что это тот самый хэш, или очень близкий. Тем более, не используя GPU, и на хэшах, где использовалась соль (любая).
Никто так и не объяснил, что не так с mysql. Один человек жаловался на особенность mysql_connect на Тостере, что функция не создаёт ему новое соединение, если не передан четвёртый параметр — но это называется "неумение читать документацию", библиотека тут ни при чём. То, что в неё давно не пилят какие-то новые фичи — не проблемы разработчика, коль скоро эти фичи ему не нужны.
С этим я согласился и исправил :)
С чего вы взяли что пароль(!) хранится в сессии? Такое ощущение, что вы вообще не читали статью, либо читали её через абзац. В сессии хранится хэш. Причём другой, не тот, что в БД. Как вы и предложили, ровно таак и работает это.
Частично согласен, что это может создавать неудобства, но это не доставляет сильных проблем обычному юзеру, поскольку автоматический перелогин происходит мгновенно. Да, это незачем, возможно, это глупость… Впрочем, не глупость. Это позволяет записывать в лог каждое изменение IP пользователя. Может я как администратор хочу знать, с каких провайдеров и как долго человек сидел на моём ресурсе? :)
- Вы зря настроены так против Joomla. Там прекрасный код в стиле ООП. И судя по тому, что я слышал о Wordpress (и частично видел сам) Joomla намного лучше. Это просто земля и небо. Да и API для расширений там очень и очень вменяемое. Смотрел видеоуроки даже по написание расширений под неё.
P. S. К SVN какие претензии? :)
VolCh
12.03.2017 23:22+1Никто так и не объяснил, что не так с mysql
Если того, что уже практически не поддерживается, мало, то, навскидку, ничего не знает о транзакциях и подготовленных выражениях.
kruslan
13.03.2017 00:351. Видимо мы разные вещи читаем. Пост от 2013-го года (4 года прошло!!) — 2,2 млрд. хешей в секунду. Не говоря уже о том, что сам md5 взламывают с 2009-го года. Добавим сюда коллизии, готовые rainbow tables и… Не могу найти ни одной причины, чтобы юзать md5 в 2017-м году. Особенно с учетом того, что есть готовые функции, которые делают эту работу намного проще, удобнее и надежнее. За UnitPay спасибо — не буду юзать, раз все так плохо.
2. Ну как объяснить… Ок, давайте попробую так: пилите-пилите проект, разросся он до нескольких гигабайт и тут решили переехать на новую версию php (7-я реально сильно быстрее 5.х). И? Начинаются костыли и рвание волос в одном месте, т.к. использование различается кардинально. Поверьте, не на ровном месте это говорю — проходил на личном опыте, когда надо было обновить проект с историей более 10 лет. Это только одна из причин, их можно легко набрать пару десятков.
4. видимо не внимательно прочел, прошу прощения.
5. Эмм…
>Это позволяет записывать в лог каждое изменение IP пользователя.
Как это связано с аутентификацией? Логи — это совсем другое. Логируйте смену ip, в чем проблема-то? Но ip точно не должно быть частью авторизации/аутентификации.
6. Ммм… Давно не трогал, решил посмотреть — может что изменилось… Ан нет… god-объект Application, по всему коду синглтоны, за такое руки оторвал-бы, тут «на всякий случай»? И это я пару файлов наугад ткнул. По поводу вордпресса — я вроде не предлагал учится на его коде).
>К SVN какие претензии? :)
Их слишком много) От тормозной работы (т.к. только diff, а не полная копия), до stash и удобства разруливания конфликтов.m0Ray
13.03.2017 01:20-2> >К SVN какие претензии? :)
> Их слишком много) От тормозной работы (т.к. только diff, а не полная копия), до stash и удобства разруливания конфликтов.
И вот тут позвольте не согласиться.
https://svnvsgit.com/
Я лично считаю SVN удобнее, чем кривое поделие линупса трольвальдса. Удивляюсь, как он этим софтом 95% ЦА умудрился «развести». Я не повёлся.
Хотя при всём этом использую вокруг себя почти исключительно linux.
Не холивара ради.kruslan
13.03.2017 01:54Хм… А с чем именно не согласны? С тем, что svn работает медленее? Или с тем, что разруливание конфликтов в snv связан с трагедией, когда идет переименование директорий?
А насчет ссылки… Обсуждалось-же уже на хабре. Как говорится — «ложь и провокация»)))m0Ray
13.03.2017 01:58-1Вот ни с чем практически не согласен. Ни с медлительностью, ни с трагедиями. Вы просто не умеете его готовить.
И да, УМВР.
Не заманите вы меня на ваш хромой git, не пытайтесь.kruslan
13.03.2017 02:23Хм… Ну я и не заманиваю. На вкус и цвет…
А что касается скорости/юзабельности — лично я на свн уже ни ногой никогда. Использовал лет 5-7 (в основном из-за возможности lock/unlock + исторически).
>Вы просто не умеете его готовить.
Возможно, даже не спорю… Но отвечу в вашем стиле: «Не заманите вы меня на ваш хромой svn, не пытайтесь.»)m0Ray
13.03.2017 02:31Я SVN использую несколько дольше, на него переполз с CVS. Ну это чтобы временные рамки как-то дать.
От git, хоть и вынужденно приходится его использовать в некоторых проектах — ничего, кроме тошноты и проклятий в адрес разработчика.
Полагаю, что Торвальдс вас просто успешно затроллил. Он сказал, что не используют git только moron-ы, и вы повелись.
Есть хорошая статейка тоже на эту тему — «Proud to be a moron». Вот я вполне proud.kruslan
13.03.2017 08:58А можете чуть подробнее рассказать, что именно вызывает «тошноту»? Кроме эмоциональной составляющей. В чем svn удобнее?
m0Ray
13.03.2017 21:55-1Прежде всего: если коммитишь в SVN, оно коммитит. Если коммитишь в git, он делает непонятно что, в чём без чтения документации каждый раз не разобраться, после чего надо выдавать ещё какие-то непонятные команды, чтобы код таки попал в сетевой репозиторий. Почему этот интерфейс нельзя было сделать по-человечески, непонятно.
Если ты хочешь вытащить определённую ветку из SVN, она просто вытаскивается. Вокруг git опять пляски с бубном.
При работе с проектом, где используется git, у меня очень много времени уходит на борьбу с ним. Например, на написание скриптов, которые делают с его помощью то, что с SVN делается одной командой.
git неудобен, он отнимает у меня гораздо больше времени, чем SVN. Локальный репозиторий только вносит дополнительные трудности и ни разу ничем мне не помог.oxidmod
13.03.2017 23:11git распредленній и синкает только то, что вы решили сами засинкать. Локально вы можете держать 100500 веток, мерджить, черипикать, ребайзить что угодно и когда посчитаете что код готов — запушить одну финальную бранчу и оформить по ней пулл-реквест. Даже если вам влом разбираться, то освоить пулл и пуш может даже первокурсник.
m0Ray
13.03.2017 23:59-2Когда я хочу коммитить — это значит я хочу коммитить. Не надо думать за меня, что мне на самом деле надо. Ненавижу молотки, которые задают вопросы (винда, например) или не бьют туда, куда я хочу (git, например).
kruslan
13.03.2017 23:11+1Ну хоть понятно стало, что вы просто не хотите меняться…
Если коммитишь в git, он делает непонятно что, в чём без чтения документации каждый раз не разобраться
Если коммитишь в гит — код именно коммитится. В локальную репу. И это огромный плюс. Позволяет разделять задачу на мелкие подзадачи и выполнять их отдельными коммитами, а в ветку пушится общий результат.
после чего надо выдавать ещё какие-то непонятные команды, чтобы код таки попал в сетевой репозиторий
Это git push не понятный?)) Ну оок…
При работе с проектом, где используется git, у меня очень много времени уходит на борьбу с ним.
Сорри, но в это я не верю. От слова совсем. Скажем так — если вы действительно используете гит, то либо юзаете 5-6 комманд (которые запоминаются через минуты 2-3), либо используете возможности ide/gui/etc. В любом случае, получается точно не сложнее чем с svn. А вот разруливать конфликты в гите значительно удобнее.
Например, на написание скриптов, которые делают с его помощью то, что с SVN делается одной командой.
А можно пример подобного? Мне реально интересно. Не смог вспомнить ни одного случая, когда svn был-бы проще и удобнее. Мне вот часто необходимо слить несколько коммитов в 1, объединить несколько веток в одну, поправить часть кода и запушить в новую ветку, не трогая мастер. Такое проще в svn сделать?
Я не троллю, мне реально интересно. Последний раз, когда трогал svn, последний был версии 1.5 или 1.6, уже точно и не помню. Тогда использование его было целой трагедией. Сейчас многое поменялось?m0Ray
14.03.2017 00:13См. выше, мне нужен молоток, а не какой-то непонятный инструмент, который не забивает гвозди.
Как отключить локальную репу в git? Я знаю ответ на этот вопрос: никак. Остальное меня мало волнует. Приходится вынужденно использовать молоток с кривой ручкой, так как заменить её нельзя.
Я пишу код и хочу, чтобы он, чёрт побери, попал в сетевую репу в нужную ветку. В SVN это делается одной командой. Зачем мне инструмент, который требует для этого больше команд?
Использую командную строку и в ней только два «IDE» — vi и mcedit.
Так вот, замаялся. К этим «5-6 командам» куча неочевидных модификаторов и прочего. Иначе оно регулярно отказывается что-либо делать. Каждый раз — в документацию или в гугл, потому что непонятно, как разрулить ошибку, причина которой в документации описана только общими словами. И каждый раз какое-нибудь новое вылезает.
Разруливать конфликты в git — да только при одном упоминании этого у меня начинается истерика, хотя я очень спокойный и невозмутимый человек. Я начинаю кидаться телефонами и ронять стулья при этом.
Зачем сливать коммиты?
Не вижу проблем в SVN при объединении веток или коммите в новую. Понимаете — коммите. Не пуше каком-то, я не понимаю что это такое и зачем это нужно. Я отправляю свой код в сетевой репозиторий, и это — коммит. Зачем мне другие действия? Мне нужен коммит. А он в git работает не так, как мне надо. Или там этим словом называется не то, что мне надо. Это вносит путаницу. И лично меня — бесит неимоверно.kruslan
14.03.2017 00:47Как отключить локальную репу в git?
А как в svn сделать локальные репы?
Я пишу код и хочу, чтобы он, чёрт побери, попал в сетевую репу в нужную ветку.
Круто. git commit & git push. В чем проблема? А как сделать в svn, чтобы в сетевую репу не попали куча разных коммитов, а попал только один, финальный?
В SVN это делается одной командой.
Верно. Потому (только не злитесь) что svn ущербен. На большее, кроме как получить/отдать, он от рождения не способен. Да, в простых случаях этого хватает. Но не всем и не всегда.
Зачем сливать коммиты?
Чтобы в истории видеть 1 коммит = 1 задаче, но при этом в разработке дробить эту задачу на 100500 мелких и решать их отдельно разными коммитами.
Не пуше каком-то, я не понимаю что это такое и зачем это нужно.
Ну так вот она проблема, а не в гите ;). Ну серьезно.
Не вижу проблем в SVN при объединении веток или коммите в новую.
Я тоже в гите таких проблем не вижу. Но коммит, для меня, это локальное действие.
Я отправляю свой код в сетевой репозиторий, и это — коммит.
Да, в svn это «коммит», т.к., повторюсь, он ущербен от рождения. Как будет работать такой коммит в самолете, например? Мне вот необходимо разделение:
коммит — фиксирование изменений кода
пуш — обновление кода в ветке
И все сразу становится на свои места. А что такое коммит в svn? Только обновление кода. Теперь представим, что необходимо во время разработки переключаться между 3-мя ветками (пусть, для простоты понимания, мы работаем с микросервисами). Как в таком случае быть с svn? Удобно?)
Это вносит путаницу. И лично меня — бесит неимоверно.
Нет. Ни гит, ни svn путаницу не вносят — их вносите вы сами. Вас-же не бесит, что у велосипеда и мотоцикла по 2 колеса, но работают они иначе, да и пользуются ими совсем по разному? А чай вы из тарелки ложкой употребляете? Нет-же, верно? Так и тут — если нет желания, найдется 100500 причин (причем местами довольно смешных) чтобы только себя позлить.
Честно, как только svn научится работать с локальными изменениями, объединением/разделением коммитов (в том числе с возможностью удалить/отредактировать 3-й из 10-и коммит) — тогда я начну воспринимать эту детскую игрушку более-менее серьезно.
Но если вас устраивает svn — используйте. Повторюсь — на вкус и цвет… Мне вот hg совсем не подошел, а svn уже не достаточен — потому и git. Да, в гите тоже есть свои неудобства, свои кривоватости и прочее, но они как-то проще что-ли…m0Ray
14.03.2017 01:08-1Зачем локальные репы в SVN? Они мне не нужны. Если мои репы лежат на моём домашнем сервере, по отношению ко мне они локальны.
Зачем мне две команды на одно действие? Глупость какая-то.
SVN делает ровно то, что надо. Зачем мне или другим разработчикам то, что делает не то, что надо?
Вы хотите спрятать подробности разработки от сообщества? Не понимаю, зачем это надо. Мне лично нечего скрывать в своём коде.
Причина в том, что мне не нужны эти операции по отдельности, потому я не понимаю, зачем их разделили. Я не вижу смысла в их разделении, это по сути одна операция. Приведите пример, зачем это может быть нужно.
Зачем работать с 3 ветками одновременно? Создайте свою и работайте в ней, потом затащите изменения из неё в другие. Создаёте проблемы на пустом месте.
Бесит меня то, что git повсеместно навязывается. Даже в такой относительно мягкой форме: «фу, он использует SVN? извращенец!» Нет альтернативы, везде только git, даже в сообществе моего любимого инструмента (Drupal). Я теперь не могу работать над своим кодом в сообществах, используя SVN, понимаете? Только на мой домашний сервер эта зараза не пробралась, да ещё кое-где в сети есть островки стабильности. Вот это бесит, а не то, что git такой.
А для меня извращенцы — это пользователи git (не я первым начал называть пользователей иных продуктов moron-ами). Но с ними ситуация примерно как с гомосексуалистами или поклонниками путина — среди моих знакомых вроде их и нет, а выйдешь на улицу или посмотришь телевизор — обязательно наткнёшься.kruslan
14.03.2017 01:22Зачем мне две команды на одно действие? Глупость какая-то.
Это разные действия).
Вы хотите спрятать подробности разработки от сообщества? Не понимаю, зачем это надо. Мне лично нечего скрывать в своём коде.
Прятать? Вы о чем? Я не хочу, чтобы недоделанная задача повлияла на пару десятков других разработчиков. В svn это сложно.
Причина в том, что мне не нужны эти операции по отдельности, потому я не понимаю, зачем их разделили.
А многим нужны именно по отдельности. И желание появилось не на ровном месте.
Приведите пример, зачем это может быть нужно.
Я уже приводил выше: решение одной большой задачи итерационно, разбивая ее на множество мелких.
Зачем работать с 3 ветками одновременно? Создайте свою и работайте в ней, потом затащите изменения из неё в другие. Создаёте проблемы на пустом месте.
Можно я не буду на это отвечать?)))
Я теперь не могу работать над своим кодом в сообществах, используя SVN, понимаете?
И это хорошо! Чем меньше плохого инструмента в обращении — тем лучше.
Мне вот не нравится drupal, но это не означает что он плохой, верно? Хотя нет — для меня он ужасен.
А для меня извращенцы — это пользователи git
На вкус и цвет… Если-бы svn был удобен — с него не убегали бы. А с него бегут. Не только в git, но и в hg и в bazaar. Бегут именно по причине того, что svn не дает работать.
Думаю, на этом и закончим. Мне уже понятно, что у вас чисто эмоциональная неприязнь инструмента.m0Ray
14.03.2017 01:40-1Это одно действие — отправка локального кода в сетевой репозиторий.
Большая задача — создаёте ветку и в ней работаете, не трогая основную. Опять какие-то искусственные проблемы на ровном месте и героическое их решение.
Характерно, кстати: я заметил, что многим пользователям git не нравится стройный, логичный, крепко сшитый Drupal. У них вечно какой-то хаос с коммитом нерабочего кода, метанием между ветками и прочие непонятные проблемы.
Наверное, причина в том, что git позволяет говнокодить, а SVN требует грамотного подхода. Работать SVN позволяет прекрасно. А работу любят не все, вот и «бегут» туда, где больше позволено.
Моё эмоциональное неприятие вылезло из чисто практического опыта: мне именно git в работе доставил больше всего задержек и неудобств. Сначала я честно пытался понять, что же я делаю не так. Но в конце концов пришёл к выводу: это, скорее всего, намеренная провокация или троллинг. Ибо не может человек, написавший сотни тысяч строк кода, не знать, как разработчик хочет работать. Или он сознательно хотел «переформатировать» мозги разработчикам, подсадив их на этот инопланетянской логики инструмент, воспользовавшись свои авторитетом. Но я пока ещё не растерял человеческий здравый смысл и авторитетов не признаю. Потому у меня «не срослось».
popov654
15.03.2017 18:06-2Между прочим, Хромиум использовал именно SVN раньше, в 2013-ом по крайней мере точно, когда я впервые выкачивал их исходники. Ну и мы в вузе использовали SVN с первого курса. Поэтому да, возможно во мне говорит привычка. Но я всё-таки за централизованный подход. Любая децентрализованная система — это обычно хаос. В SVN один репозиторий и много рабочих копий у разработчиков. В Git у каждого разработчика по репозиторию. Что за бред вообще?) И как это синхронизировать, чтобы твой репозиторий был постоянно актуален. Жесть же. И логически (при конфликтах), и по ресурсам на синхронизацию.
lair
15.03.2017 18:17И как это синхронизировать, чтобы твой репозиторий был постоянно актуален.
Приблизительно так же, как синхронизируются локальные рабочие копии с центральным репозиторием.
А зачем мне постоянно актуальный репозиторий, кстати?
И логически (при конфликтах),
Конфликты — они между ветками обычно, а не между репозиториями, так что здесь нет никаких дополнительных накладных расходов.
popov654
15.03.2017 18:01Чтобы в истории видеть 1 коммит = 1 задаче, но при этом в разработке дробить эту задачу на 100500 мелких и решать их отдельно разными коммитами.
Что за маниакальное желание делать коммит каждого мелкого изменения? Вам кнопочки Save мало? Я уже молчу про то, что многие IDE поддерживают Local History для отката изменений.
Если же изменений много, и это целая подзадача — наверное, логично сделать обычный сетевой коммит, как он делается в SVN.
Да, в svn это «коммит», т.к., повторюсь, он ущербен от рождения. Как будет работать такой коммит в самолете, например?
А зачем вам делать коммит в самолёте? Достаточно сохраниться, а закоммитить всегда можно при приземлении. Вы придумываете проблемы там, где их нет)
lair
15.03.2017 18:03Что за маниакальное желание делать коммит каждого мелкого изменения?
А почему нет? Это бывает удобно.
А зачем вам делать коммит в самолёте?
Чтобы видеть историю работы.
popov654
15.03.2017 18:11Бывает, но не всем. Давайте тогда остановимся на том, что это личные пристрастия каждого. И не будем никого оскорблять)
Кроме того, есть и аналоги, позволяющие видеть историю изменений, но при этом не держать локально целый репозиторий (в любой системе контроля версий). Простейший — это "вшитые" в IDE модули локальной истории, но я верю, что есть варианты ещё мощнее (но не такие мощные и универсальные, как тот же Git). Просто мне это было не нужно, не изучал вопрос.
P. S. И правда может быть удобно откатить мелкий фрагмент изменений, но на то, чтобы во время написания кода думать о том, где провести границы между этими фрагментами — уходят мыслительные ресурсы и время. Тут спорно, будет ли выигрыш. Я бы не заморачивался :)
lair
15.03.2017 18:15+2Бывает, но не всем. Давайте тогда остановимся на том, что это личные пристрастия каждого. И не будем никого оскорблять
Это говорит человек, написавший слово "маниакальное"?
Простейший — это "вшитые" в IDE модули локальной истории
Для меня не работает.
верю, что есть варианты ещё мощнее (но не такие мощные и универсальные, как тот же Git).
… но зачем, если просто есть DVCS, которая делает и это, и контроль версий для совместной разработки? Зачем использовать два инструмента, когда есть один, который прекрасно справляется с задачей?
И правда может быть удобно откатить мелкий фрагмент изменений, но на то, чтобы во время написания кода думать о том, где провести границы между этими фрагментами — уходят мыслительные ресурсы и время
У кого-то уходят, у кого-то — нет. Я задачу заранее разбиваю на кванты обычно, потому что иначе она может выглядеть неподъемной. Сделал квант — сделай коммит.
И это мы еще переключения не рассматриваем.
VolCh
15.03.2017 20:04Что за маниакальное желание делать коммит каждого мелкого изменения?
Как минимум, это удобно для ревью. Ну и если используется что-то типа TDD, то даже это минимальное изменение не нарушает работу кода. Коммитить неработающий код — обычно зло. В процессе работы над новой фичей часто код становится неработающим, а потом становится работающим, пускай фича пока и н ереализована до конца. Имеет смысл фиксировать шаги когда код рабочий.
m0Ray
14.03.2017 00:31-2Кстати, могу поделиться почти универсальным способом устранения проблем с git. Возникают они регулярно, а надёжного способа борьбы с ними я не нашёл. Итак, если при коммите возникла какая-то очередная непонятная ошибка:
1) Скопировать код во временный каталог.
2) Удалить каталог.
3) git clone (не забыть кучу параметров про ветки и всё такое)
4) Скопировать старый код поверх клона и закоммитить.
5) Вспомнить, как таки отправить свой код в сетевой репозиторий.
Иногда такое приходится делать по нескольку раз в день. Полноценной работой это назвать я не могу.oxidmod
14.03.2017 00:37вот это у вас подгорает.
m0Ray
14.03.2017 00:42трольвальдс — тонкий тролль, да. Умудрился так умудрился подгадить так, чтобы подгорает даже у такого спокойного человека, как я. Наступить на самое больное место — не дать спокойно заниматься программизмом — это надо уметь.
Но проблема не в том, что есть git. Ну есть он и есть, чёрт бы с ним. Но! Меня заставляют им пользоваться. Вот это плохо. Вот это бесит.kruslan
14.03.2017 00:53трольвальдс — тонкий тролль, да.
Не нравится мне он, но в вашем случае проблема точно не в нем и не в троллинге ;)
kruslan
14.03.2017 00:52Странное решение проблем. Да еще и «несколько раз в день».
Итак, если при коммите возникла какая-то очередная непонятная ошибка
Например? Мне кажется — вы сейчас сильно лукавите. Если проблема в коммите — у вас проблема с настройками и/или правами. Если в пуше — значит у вас конфликт, который легко разруливается. А ваш «рецепт» похож на мазохизм, из серии «пусть мне будет плохо, но я так хочу»…m0Ray
14.03.2017 01:11Нет никаких проблем с настройками и правами. Просто почему-то рушатся локальные данные. Иногда чинится каким-то шаманством вокруг веток, иногда нет. После удаления, полного клона и записи нового кода поверх всё чинится.
Не знаю, что это за проблема и знать не хочу. Я хочу кодить, а не бороться с глюками неудобного инструмента.oxidmod
14.03.2017 01:13Я ничего не трогала, оно само!
m0Ray
14.03.2017 01:16Именно так. И вы не поверите, в винде таки всякое бывает «само», потому я уже много лет ей не пользуюсь.
Я отвык от такого поведения софта, и не желаю к нему снова привыкать. Молоток должен забивать гвозди, а не кобениться в произвольно выбранный момент.kruslan
14.03.2017 01:26Может стоит научится пользоваться молотком? Да, молотки бывают разные и для разных целей. А еще у них бывают разные ручки — одни удобнее, другие нет.
Вот svn в качестве молотка отвратителен — сбитый боек, треснутая ручка, не работает когда не подключен к интернету, не работает, когда нужен сразу нескольким трудягам — один ручку забрал, другой боек и ни у одного не получается забить гвоздь.
А когда им обоим говорят — вот, возьмите бесплатно каждый по новому молотку с удобной ручкой, говорят нет, у новых молотков ручка слишком удобная, не привычно, тяжело себе по пальцам ударить…m0Ray
14.03.2017 01:44git — это молоток с двумя резиновыми ручками, стеклянным бойком и оптическим прицелом. Спасибо, но я лучше стареньким, с треснутой ручкой, зато надёжно.
Кстати, а по пальцам, говорят, больно, да? Ни разу вот не попадал. Мелкие гвозди расчёской придерживаю, например, а по крупному промазать — это ж какие кривые руки надо иметь?
m0Ray
14.03.2017 01:47Когда не подключен к интернету — зачем тебе VCS? Сидишь, кодишь локально, попутно материшь провайдера по телефону. Интернет нужен только для того, чтобы залить код в сетевой репозиторий или получить обновления. А git что, для этого астральными каналами пользуется?
VolCh
14.03.2017 07:57+2VCS не про сеть, это просто контроль версий. А версии бывают и локальные. Git разделяет собственно контроль версий и работу с удаленными репозиториями, ка частный её случай. Для git существование удаленного репозитория — малозначащий в процессе разработки нюанс. Для svn — основа процесса.
Git именно что позволяет разрабатывать не думая о существовании сетевых репозиториев пока не решишь залить код в сетевой репозиторий или получить обновления. SVN же принуждает работать с сетевым репозиторием, даже если вообще удаленный репозиторий не нужен, если ни с кем делиться не собираешься.
m0Ray
14.03.2017 08:09-1Зависимость от сети — мало значащий нюанс. VCS нужна для обеспечения совместной работы, которая всё равно невозможна без сети. Плюс ведение истории изменений, чтоб ничего не пропало и всегда было видно, кто накосячил.
Если я ни с кем не собираюсь делиться кодом и работаю над проектом один, я вообще не буду заморачиваться никакими VCS — хватит и обычных бэкапов. Свой код, в который никто не лезет, я прекрасно знаю и так.
Если проект командный и у меня вдруг нет интернетов, я буду спокойно сидеть и кодить, а потом, когда сеть появится — залью всё одним коммитом. Никто от этого не пострадает, в комментарии к коммиту я просто напишу чуть больше.VolCh
14.03.2017 08:43VCS нужна для обеспечения совместной работы
Вот, наверное, откуда ваше неприятие git и подобных систем. Вам она нужна только для обеспечения совместной работы, а я использую её для обеспечения работы вообще, о том, что она совместная — нюанс, о котором вспоминаю только когда нужно поделиться своими результатами или получить чужие. Но коммиты, создание веток, переключение между ними, слияние и т. п. — это не касается этого нюанса, это просто обычный процесс работы, независимо от того, совместная она или нет, создан сетевой репозиторий или нет. И бэкапами сложно заменить, с одной стороны, а с другой, можно представить локальную работу с гит как удобную систему работы с множеством бэкапов, просмотром диффов между ними, отслеживанием связей какой от какого "вырос", слиянием и т. т.п.
m0Ray
14.03.2017 08:50-2То есть вы не знаете своего кода и вам нужны костыли, чтобы помнить, что в нём и откуда? Я поражён.
Ну, тогда мне становится понятна популярность git. Инвалиды считают себя важнее здоровых людей и навязывают инвалидский подход всем, превращая всех в инвалидов. И ведь у них получается, блин… 8-(
Нет, мне эти костыли не нужны. Но из-за них меня по сути лишили нормальной VCS. Обидно, досадно, но ладно. Жизнь — штука несправедливая.VolCh
14.03.2017 09:09+1Мне нужны "костыли", чтобы этого не нужно было помнить, особенно когда в рамках одного проекта делаю несколько задач параллельно. Да даже при чисто линейной разработке (что большая редкость) последовательность коммитов в VCS куда удобнее, чем последовательность обычных бэкапов. "Вкалывают роботы — счастлив человек" ©
m0Ray
14.03.2017 09:54-1Мне доставляет удовольствие «крутить» в голове систему. Или несколько. И мне хватает своей головы на всё, даже когда я занимаюсь несколькими проектами одновременно. Мне не нужны костыли, я рад на своих «ногах» бегать, прыгать и танцевать. Да так и быстрее.
Бэкапы удобнее: зашёл в каталог, посмотрел файлы. Мне даже комментарии не нужны, я помню, что и в какой последовательности делал. С VCS надо куда-то выгружать данные, прежде чем их можно будет посмотреть.
М-да, я думал, любой разработчик так умеет. Удивили, нечего сказать.VolCh
14.03.2017 10:33И так со всеми своими проектами помните последовательность? За все "около 18 лет"? А что делаете когда важна не временная последовательность, а логическая? Её тоже помните?
Зачем куда-то что выгружать? Всё дерево истории можно прямо из каталога проекта смотреть, хоть содержимое файлов в коммите, хоть различия содержимого в любых коммитах в любых ветках. Да, можно сделать что-то похоже на снэпшотах/бэкпах, сделать в проекте папочку backups, в ней с пяток минимум папочек типа "production", "redesign", "feature-1", "bugfix-2" и т. п., в них папочки на каждій значимій шаг с комментирующим названием типа "merge with feature-1", "redesign logo", "add mock for backend", "workaround" и т. п., копировать туда проект после каждого шага, сравнивать их между собой стандартным diff-ом, сливать как-то. Но в итоге получится папочка типа .git
m0Ray
14.03.2017 10:45-1Всё сразу в голове не держу. Но если открою каталог с проектом и гляну структуру каталогов, открою пару файлов — проект «подгружается» по ассоциативным связям и я вспоминаю.
Нет, такого изврата я не держу. Бывает пара бэкапов, которые я делаю перед масштабным рефакторингом или удалением чего-то — чисто чтобы не потерять код. Бэкапы продакшна зачастую есть. Ну и всё. Мне норм.
andreymal
14.03.2017 11:22+1Вот буквально вчерашний пример. Откопал сайт, к которому не прикасался год. Делал его я один, соответственно никакой удалённый репозиторий ради командной разработки не был нужен. Откопал, потому что заметил, что один пункт меню пропал (не слишком важный пункт, поэтому целый год никто ничего не замечал). Открываю nav.html — нету пункта. При этом я точно помню, что этот пункт раньше был. Соответственно, логично захотелось посмотреть, каким nav.html был раньше.
Что бы было, если бы были только бэкапы? Да ничего. Народ обычно удаляет старые версии бэкапов (особенно через целый год-то), вот и я бы тоже удалил всё старое и оставил бы только последний актуальный бэкап. Но предположим, все старые бэкапы есть — и как бы я в них искал, когда пропал пункт меню из nav.html? Сидеть распаковывать десятки-сотни архивов и смотреть содержимое nav.html в каждом? Данунафиг блин.
Но зато у меня есть локальный репозиторий git! Простейший
git log nav.html
— и вот я уже вижу все изменения этого конкретного файла. Не прошло и минуты, а я уже нашёл коммит, в котором пункт меню пропал. 4 апреля 2016, описание «Rewrite nav.html». Всё стало ясно: отрефакторил файлик, а пункт меню просто забыл добавить и не заметил. В итоге я просто скопировал пункт меню из старого nav.html в новый, не пришлось писать ни строчки нового кода.git add nav.html && git commit -m 'Restored some nav items'
Пример примитивный, но ничего не мешает случиться чему-нибудь аналогичному на более глобальных изменениях, вроде выпиливания большой фичи, которую внезапно понадобится вернуть. Бэкапы — не замена контролю версий, контроль версий — не замена бэкапам. Если вы способны помнить всё, что делали во всех своих проектах, к которых не прикасались годами — поздравляю, у вас на удивление хорошая память, такая очень мало у кого есть :) А я помнить не только не могу, но и не хочу: зачем, если помнить за меня может обладающий бесперебойной памятью git, причём не требуя удалённого репозитория?) А крутить в голове я лучше буду те проекты, которыми занимаюсь в настоящий момент, а вышеупомянутый сайт к ним не относится.
С VCS надо куда-то выгружать данные
О чём тут речь? В моём случае кроме
git add
иgit commit
я ничего не делал, а просмотреть всё могу как простымgit log
, так и каким-нибудь графическимgitk
m0Ray
15.03.2017 02:47Пример очень примитивный. Перед крупными изменениями я бэкаплюсь, а мелкие восстановить — дело пары минут. Не убедили этим примером.
Я и кручу в голове только те, которыми занимаюсь сейчас. Но переключиться и «раскрутить» какой-нибудь архив — не проблема.
Речь о том, чтобы получить полную копию исходников на какой-то момент. Они, насколько мне известно, не лежат в открытом виде, «как есть», а представляют собой архивы diff-ов и т.п. Разработчики VCS же не такие идиоты, чтобы хранить полные копии на каждый чих — инкрементальные архивы там. Мне не нужны логи — мне нужна копия исходников проекта по состоянию на какой-то момент. Это делается относительно просто, но это всё равно дополнительная операция.andreymal
15.03.2017 10:03+2Что ж, поздравляю, вы уникальный :) Мне (и, думаю, многим другим) в первую очередь нужны и важны именно логи.
Перед крупными изменениями я бэкаплюсь, а мелкие восстановить — дело пары минут.
Даже спустя год? И храните все столь старые бэкапы? Вы всё ещё уникальный, можете гордиться этим))
popov654
15.03.2017 18:24Ну кстати, если графику в бэкапы не включать — смысл их удалять вообще? Код весит не так много, и отлично сжимается зипом :)
Я регулярно создаю бэкапы перед крупными изменениями, а старые никогда не удаляю. Пример: был сайт, который я делал и поддерживал примерно год. За это время накопилось 40 бэкапов клиентской части и 32 бэкапа админки. Плюс следующие два года я поступал немного по-извращенски, внося вручную изменения в самые последние 1-2 архива во время важных security-фиксов и исправлений крупных багов.
Проект довольно крупный. При этом мне ни разу даже в голову не пришло удалить какие-то старые архивы. Так что я с коллегой солидарен, пока код знаешь хорошо, и есть бэкапы (в идеале ещё и с краткими чейнджлогами) — VСS вообще не особо нужна.
andreymal
15.03.2017 18:32+2Если пользовать VCS, бэкапы вообще не особо нужны. ;)
Хранение и просмотр изменений — непосредственная задача VCS. Пытаться адаптировать под это бэкапы — костыль и жевание кактуса. Делать по новому бэкапу с чейнджлогом на каждое мелкое изменение — какая-то глупость, а для VCS (кроме SVN, я так понимаю, лол) совершенно нормальная и очень полезная практика. И для VCS никакой графики выпиливать не надо.)
примерно год. За это время накопилось 40 бэкапов
В то время как сделать 40 коммитов к гите дело нескольких дней — история получается в разы подробнее, а откатывать отдельные изменения в случае чего (да, их иногда приходится откатывать) гораздо проще.
пока код знаешь хорошо
Вы тоже из тех, кто способен помнить старые крупные проекты годами? Ох, вас уже целых двое.
oxidmod
14.03.2017 09:32А вы видать сложней визиток ничего не делаете)) Тут да, даже свн не нужен
m0Ray
14.03.2017 09:49Я делаю разные, и нередко очень сложные проекты. Но ни разу мне не понадобились костыли для того, чтобы держать в уме структуру проекта и план его разработки. Мне казалось, этим умением обладают все разработчики и архитекторы ПО. Это приходит с опытом, и это доставляет мне удовольствие — вертеть в голове будущую систему и разглядывать её в мелочах и в общем.
Как вообще можно что-то разрабатывать без такого умения?
Нет, это серьёзно? Вы без VCS не можете даже средней руки сайт набросать?oxidmod
14.03.2017 10:02+1Я не вижу смысла разбазаривать ресурс мозга на то, чтобы помнить в каком там каталоге лежит та версия, на которую понадобилось откатиться.
Мне приятно грепнуть по комит меседжу в истории номер таски и спокойно увидеть в IDE дифф к текущей ситуации… или между произвольными моментами времени.
И да, помнить 20-30-100мб текста наизусть? Вы серьезно? Или всеже у вас не такие серьезные проекты, как вам кажется?m0Ray
14.03.2017 10:19Это не разбазаривание, а тренировка и поддержание в тонусе. И да, ещё я умею считать в уме, без калькулятора, представляете? Для меня было открытием что не все это умеют. До определённых пределов, конечно считаю, но в магазине за смартфоном не лезу, готовя перед кассой нужную сумму. Как показывают исследования — всё это способствует уменьшению вероятности наступления старческого слабоумия. Не думаю, что до него доживу, но на всякий случай… И в конце концов мне это нравится.
Я помню не сам текст, а что-то вроде хэша. Память у меня не абсолютная, разумеется, но в общих чертах я помню где и что должно лежать, и быстро нахожу. Ядро linux я в одиночку не разрабатываю, конечно. И то наверняка бы помнил очень многое, если бы сам это делал. Чужой код у меня «хэшируется» медленнее и менее надёжно, лучше запоминается именно «выстраданное».
lair
14.03.2017 12:13+1Если проект командный и у меня вдруг нет интернетов, я буду спокойно сидеть и кодить, а потом, когда сеть появится — залью всё одним коммитом. Никто от этого не пострадает, в комментарии к коммиту я просто напишу чуть больше.
То есть идея про атомарные изменения вам чужда?
m0Ray
15.03.2017 02:48Что считать атомарным изменением? Изменение одного байта? Одной строки? Одной функции? Одной фичи?
Да, чужда.lair
15.03.2017 11:25Что считать атомарным изменением?
Одну задачу.
Я вот, например, регулярно сначала одним коммитом делаю собственно доработку (багфикс или изменение), а потом следующим — рефакторинг. Так по истории легче определить, зачем сделано конкретное изменение.
lair
14.03.2017 12:12+1Когда не подключен к интернету — зачем тебе VCS? Сидишь, кодишь локально,
Чтобы внести одно сложное изменение, потом начать вносить следующее, имея легкий откат обратно. Я за собой заметил, что я иногда делаю локальные репозитории даже на присланных партнерами сэмплах, чтобы легко отличать мои изменения от их кода.
m0Ray
15.03.2017 02:58Я просто не редактирую напрямую чужой код. Мне присылают архив, я распаковываю его, но не удаляю. Таким образом у меня всегда есть копия оригинального кода.
Откаты же мне практически никогда не требуются, потому что я заранее знаю, что и как хочу написать. Но опять же — архивы, бэкапы. Мне норм.lair
15.03.2017 11:28+1Я просто не редактирую напрямую чужой код. Мне присылают архив, я распаковываю его, но не удаляю. Таким образом у меня всегда есть копия оригинального кода.
… а потом надо найти, какие изменения вы сделали, чтобы заработало.
Откаты же мне практически никогда не требуются, потому что я заранее знаю, что и как хочу написать.
Да вы гений. Или просто у вас очень простая система.
Но опять же — архивы, бэкапы. Мне норм.
Вам "норм", а кто-то не любит использовать костыли там, где за них уже написано решение.
oxidmod
14.03.2017 01:27За свои скромные 4.5 года в веб-разработке ниразу с таким не сталкивался.
Ни разу даже не слышал от коллег о подобной проблеме ни в одной из 3 компаний, где довелось поработать.
Сходите чтоли к бабке, пусть сглаз снимет. Яйца там откатает или что они еще делают.
зы. В лифтах не ездите только, от греха подальшеm0Ray
14.03.2017 01:50Учитывая, что проблема иногда лечится какими-то плясками с бубном вокруг веток — есть вероятность, что это «не баг, а фича». Но мне такие «фичи» даром не нужны. Мне нужно работать, а не демонстрировать чудеса branch-juggle-kill-your-momma-with-axe.
kruslan
14.03.2017 01:26+1Нет никаких проблем с настройками и правами. Просто почему-то рушатся локальные данные.
Вас не смущает, что у других подобных проблем не возникает?))))))))m0Ray
14.03.2017 01:45И с другими инструментами у меня тоже таких проблем никогда не возникает.
kruslan
15.03.2017 00:04Ох блин… Повелись на толстого-толстого тролля ((((
m0Ray
15.03.2017 02:56Напрасно вы считаете это троллингом. Я искренне недоумевал, и вот в этой ветке обсуждения мне объяснили: оказывается, у большинства разработчиков проблемы с памятью. Для меня это неприятное открытие. Примерно такие же чувства я испытал, когда узнал, что не все люди умеют считать в уме хотя бы в пределах тысячи.
И вот вместо того, чтобы тренироваться, развивать свои способности, люди с радостью хватаются за костыли. Хотя ведь могут.
git как личная запоминалка, может быть, и хорош, как может быть хорош изящно сделанный костыль с электроприводом выдвижения антигололёдного шипа. Но он мне не нужен. Как средство командной работы же он менее удобен, чем SVN, как раз из-за своей хвалёной децентрализации. Она не везде одинаково полезна.VolCh
15.03.2017 07:53+2С чего вы взяли проблемы с памятью? Зачем мне запоминать в какой последовательности я что делал 10 лет назад?
kruslan
15.03.2017 12:54+2Напрасно вы считаете это троллингом.
Нет, не напрасно. Иначе просто объяснить подобное нельзя)
оказывается, у большинства разработчиков проблемы с памятью
о_О серьезно? Т.е. вы без проблем можете помнить все изменения в коде, например, размером 200мб? Вот 2 проекта, над которыми работаю параллельно в последнее время:
Никогда не поверю, что кто-то может помнить такой объем. Отсюда вывод — вы троль.
Как средство командной работы же он менее удобен, чем SVN, как раз из-за своей хвалёной децентрализации.
Лол… Именно локальное хранилище дает большие плюсы. Я вот часто делаю различные эксперименты с помощью гита и виртуалки и мне не приходится заливать ненужный код в общий репозиторий.
Там по ссылке вам правильно сказали — вы просто не смогли осилить. И поэтому решили всех троллить, в надежде найти поддержку. Но ее не будет, потому как svn реально говно, по сравнению с git/hg.popov654
15.03.2017 18:31У вас просто реально очень крупные проекты, в этом случае, конечно, весь код помнить не реально. Но я всё равно не верю, что вы там правите ВСЁ.
Обычно разработчик в большом проекте берёт себе одну задачу. Как правило — небольшую, особенно если он не тимлид (но тимлид хотя бы сам не пишет особо код, так что тут тоже проще). А так разбиваются на команды, и над одним модулем работают человека 2-4. Вот честно скажите, вам при работе над модулем надо помнить ВЕСЬ код проекта? Правда?
Интеграция модуля в систему — это да, но API обычно чётко определены, и меняются редко. Да и API обычно делают с ядром, а не со всем на свете.
oxidmod
15.03.2017 18:35+2А как на счет того, что ингда с вашим кодом работает ктото другой? Частые коммиты с внятными меседжами своего рода десижен лог. Открыв историю файла любой разработчик сориентируется не только кто, когда и в какой ветке сделал изменение, но и почему он его сделал
popov654
15.03.2017 18:55Ну тут конечно VCS незаменима. Я про индивидуальную разработку говорил
А начался вообще этот тред со спора, нужен ли локальный репозиторий.
Моя позиция была в том, что если не делать коммиты очень мелкими (2-3 строчки кода, не являющиеся цельным изменением) — то такой коммит не нужен. А если строчек много, и есть одно или более значимых функциональных изменений — то можно в ряде случаев и в сетевой репозиторий коммит залить. Тут уже как разработчики договорятся/как в компании принято.
kruslan
15.03.2017 21:01+1Но я всё равно не верю, что вы там правите ВСЁ.
Очень зря. По первому проекту примерно 30 коммитов в сутки на команду (от меня лично — 3-4). Думаю это видно на скрине ;) И да, затрагивается абсолютно весь код, какой-то чаще, какой-то реже.
Вот честно скажите, вам при работе над модулем надо помнить ВЕСЬ код проекта? Правда?
Скажите честно — вы хоть раз работали в команде на 10-20 человек над большим проектом? Просто судя по заданному вопросу — нет. Тогда мне сложно будет вам объяснить, что как-раз НЕ НАДО помнить весь код (и особенно последние изменения) — их можно посмотреть в гите.
но API обычно чётко определены, и меняются редко.
Realy?)))) Я даже не знаю что сказать, если честно. Посмотрите на 2-й скрин, в котором код поменьше. За последние 5-6 месяцев в этом проекте переписано процентов 80 кода. Как думаете — апи остался без изменений?))))
popov654
15.03.2017 17:55+1Позволяет разделять задачу на мелкие подзадачи и выполнять их отдельными коммитами
А почему нельзя каждую подзадачу коммитить в ветку непосредственно? Не вижу в этом большой проблемы. И имхо, во многих крупных проектах делают именно так. Глянуть хотя бы репозиторий хромиума или SKIA какой-нибудь. Там довольно небольшие коммиты и мелкие изменения.
lair
15.03.2017 18:02А почему нельзя каждую подзадачу коммитить в ветку непосредственно?
Вы, наверное, имели в виду "в ветку удаленного репозитория". Так вот, потому, что код на этом этапе может быть еще не полностью готов — и, например, не проходить весь набор тестов.
Я вот, скажем, регулярно первым коммитом пишу тест (особенно если это баг). Если это попадет в общий репозиторий с CI, там начнут валиться билды.
popov654
15.03.2017 18:36Окей, с тестом — согласен, логичный сценарий.
В общем же случае — я бы просто не коммитил до тех пор, пока код не станет готов, и все тесты не будут им пройдены.
Так вот, потому, что код на этом этапе может быть еще не полностью готов — и, например, не проходить весь набор тестов.
Но если задача столь сложна, что за вечер или два её не решить — да, Вы правы, Git будет удобнее.
Хотя наверное можно извратиться и коммитить такие куски, чтобы тесты не падали. Но это потребует изрядной смекалки и лишних сил. Этот ресурс можно на другое пустить :)
lair
15.03.2017 18:39+1В общем же случае — я бы просто не коммитил до тех пор, пока код не станет готов, и все тесты не будут им пройдены.
… и все это время вам нельзя отрываться от задачи. Это, конечно, круто, но не всегда достижимо.
Но если задача столь сложна, что за вечер или два её не решить — да, Вы правы, Git будет удобнее.
У меня есть задачи, которые "решаются" неделями. И за это время я их на сервер пушу только из-за паранойи "а вдруг диск накроется" — и при этом я имею иногда почасовую историю того, что и зачем я делал, с соответствующими записями в blame/annotate.
popov654
15.03.2017 19:06В смысле, что у Вас куча задач параллельно, или так много кода требуется? В этом случае m0Ray предлагал создать отдельную ветку под свою задачу в общем репозитории. Не знаю, насколько это уместно, но вариант рабочий.
lair
15.03.2017 19:07У меня много задач параллельно. У меня, конечно, по ветке на каждую задачу, но, повторюсь, я не хочу, чтобы в общий репозиторий попадал неконсистентный код. А в локальном репозитории я могу творить, что угодно.
kruslan
15.03.2017 21:03А почему нельзя каждую подзадачу коммитить в ветку непосредственно?
На это есть огромная куча причин. Основная — в истории желательно видеть кто и что сделал В ПРЕДЕЛАХ конкретной задачи. Если над задачей работает несколько человек — это вообще критично становится. Если один — желательно видеть, какой коммит за какую часть задачи отвечает (хотя-бы для ревью, но это так-же важно для тестов и выкладки).
popov654
15.03.2017 17:39Что значит "только diff"? Объясните поподробнее. И как бы это, объём данных, которые приходится выкачивать при клонировании Git репозитория, сильно удручает. Для больших проектов это целые десятки гигабайт.
lair
15.03.2017 17:46И как бы это, объём данных, которые приходится выкачивать при клонировании Git репозитория, сильно удручает. Для больших проектов это целые десятки гигабайт.
А вам точно нужна вся история и все ветки?
popov654
15.03.2017 19:11Нет, нужен только мастер, разумеется. Да, я глупость сказал. Проблема того проекта, о котором я пишу, не в том, что в качестве VCS там используется Git, а в том, что там просто используется много всего. И это всё нельзя не скачать, иначе код не скомпилировать просто.
popov654
15.03.2017 17:50-1Пост от 2013-го года
Это называется "слышал звон, да не знает, где он". Видно, что вы вообще не разбираетесь в сути вопроса.
По пунктам:
Первого марта 2005 года было продемонстрировано первое использование указанной уязвимости на практике. Группа исследователей представила два сертификата X.509 с разными наборами ключей, но с идентичными контрольными суммами. В том же году Властимил Клима опубликовал алгоритм, позволяющий обнаруживать коллизии на обычном ноутбуке за несколько часов. В 2006 он пошел дальше. Восемнадцатого марта 2006 года исследователь обнародовал алгоритм, находящий коллизии за одну минуту!
Найти коллизию для некоторых двух хэшей — не то же самое, что взломать конкретный хэш (найти некие исходные данные, которые вернут ту же контрольную сумму). Это сильно разные задачи, и вероятность успеха сильно разная.
Большая работа была также проделана и для ускорения взлома хешей. В 2007 году Кевин Бриз представил программу, использующую Sony PlayStation3 для взлома MD5. Он сумел добиться очень неплохих результатов: 1,4 миллиарда MD5-хешей генерировались всего лишь за одну секунду!
Давайте посчитаем: за месяц с такой скоростью можно получить примерно 3628800 миллиардов хэшей. Посмотрим, как это соотносится с длиной хэша (128 бит). Math.log2(3628800000000000) = 51.688413968703216. Это даже не квадратный корень от общего числа комбинаций. Но даже если бы это был корень, чтобы подобрать все хэши, понадобилось бы примерно… 302400000000000 лет. Лет, Карл!
Мы используем вышеприведенный способ для взлома одного определенного хеша, сгенерированного при помощи алгоритма MD5. Максимальная длина возможного пароля составляет семь символов. Через какое-то время пароль будет найден (qwerty). Теперь давай попробуем взломать еще один хеш, но с немного другими условиями. Пусть наш хеш имеет вид d11fd4559815b2c3de1b685bb78a6283, а пароль включает в себя буквы, цифры, знак подчеркивания и имеет суффикс «_admin». В данном случае мы можем использовать перебор пароля по маске, чтобы упростить программе задачу
Теперь давай попробуем взломать сразу несколько паролей одновременно. Предположим, что к нам в руки попала база данных хешей паролей. При этом известно, что каждый пароль оканчивается символами c00lВ реальной жизни, если пароль не имеет вид "111111", задачу упростить таким образом не получится. Последний пример (с одинаковыми постфиксами на всю пользовательскую базу) — вообще сферический идиотизм в вакууме, в жизни такого не бывает.
kruslan
15.03.2017 21:08Видно, что вы вообще не разбираетесь в сути вопроса.
Оохх… Ну ок, пусть будет «не разбираюсь»)). Мне реально не хочется с вами на эту тему общаться.
popov654
16.03.2017 04:34-1Также важно помнить, что стойкость хэш-суммы имеет значение лишь в случае, когда база утекла с сервера. Если база утечёт — скорее всего, админ об этом узнает. В этом случае ответственный админ сразу же сбросит пароли всем пользователям. Если сайт совсем не содержит критических данных (небольшой блог или форум) — то и вовсе можно сделать рассылку и предоставить пользователям решить самостоятельно, хотят они обновить свой пароль или нет. Тут мне могут возразить, что такая утечка ставит под удар доступ юзера ко ввсем ресурсам, где есть такой же пароль. Но пароли всё равно меняют раз в 1-2 года самое крайнее, а как правило намного чаще.
Я к тому, что даже 2-3 месяца в запасе — уже немалый срок. Те же цифры, что я посчитал, хоть они и взяты не на текущий год, а на тот год, про который писалось в статье — они настолько астрономические, что, кхм, вряд ли что-то существенно поменялось.
Предлагаю в общем всем желающим провести простой эксперимент. Берёте пароль длиной 7-8 символов, сгенерированный случайно, объединяете с 32-символьной солью (тоже псевдослучайной), получаете MD5 хэш. Скачиваете соответствующий софт и пробуете взломать. И потом увидим, сколько времени для этого понадобится, и выйдет ли оно вообще.
Я даже хэшей могу накидать для такого теста.
kruslan
16.03.2017 15:05+1Ну хорошо, 1 раз отвечу…
Если база утечёт — скорее всего, админ об этом узнает.
Не узнает.
В этом случае ответственный админ сразу же сбросит пароли всем пользователям.
Если в здравом уме — нет.
Но пароли всё равно меняют раз в 1-2 года самое крайнее, а как правило намного чаще.
99% нет.
Те же цифры, что я посчитал, хоть они и взяты не на текущий год, а на тот год, про который писалось в статье — они настолько астрономические, что, кхм, вряд ли что-то существенно поменялось.
1. В посте говорилось про взлом/исследование на ноуте/PS3/видюхе.
2. Берете кластер в амазон/google и все меняется настолько существенно, что…
Берёте пароль длиной 7-8 символов, сгенерированный случайно
А пароли пользователи выбирают такие-же? По вашему, радужные таблицы не нужны в реальности?)))
Вы бы хоть основы поизучали… Меня обвинили в том, что я в этом не разбираюсь, при этом пишите такие глупости, которые я лично проходил на своем опыте… Не позорились-бы…
reaferon
12.03.2017 13:44-5Жаль, что статью заминусовали.
На самом деле, она довольно полезна для тех, кто не тупо копипастит решения, а вдумчиво читает комментарии.
Потому как именно в них рассмотрены разнообразные ошибки, которые теоретический читатель сможет избежать.andreymal
12.03.2017 13:51+2Есть опасение, что тех, кто тупо копипастит решения, всё-таки гораздо больше (правда, хз как это проверить)
nmk2002
13.03.2017 12:18Так если бы были плюсы, то как раз и началось бы копирование решения, а по минусам сразу становится понятно, что надо лезть в комментарии — читать, что не так в статье.
greabock
12.03.2017 13:53+2Уж простите, но у меня подгорает стул от того, что разработчики, с не первым годом опыта, до сих пор смешивают понятия авторизации и аутентификации.
popov654
12.03.2017 14:57-3Потому что то, что грамотно считается авторизацией, по факту мало где нужно — только в CMS и на всяких форумах. А вообще чаще авторизацией называют логин. Не надо занудствовать)
lair
12.03.2017 15:55Потому что то, что грамотно считается авторизацией, по факту мало где нужно — только в CMS и на всяких форумах.
Ну то есть вы все бизнес-системы так вот взяли и выкинули? Всю почту? Все социальные сети?
popov654
12.03.2017 16:19-1Социальные сети и бизнес-системы — это очень круто, не мой масштаб точно. Но это да, конечно)
Почта — а зачем там авторизация-то? Там обычно один пользователь. Мы же про персональные ящики?VolCh
12.03.2017 16:25+1Проверять, что пользователь пытается читать свою почту и отправлять от своего имени.
popov654
12.03.2017 16:40А, логично. Я когда делал мессенджер проверял всё это ровно так же, что мы пишем именно от себя, и в ту комнату, куда имеем доступ.
Просто там зависит от реализации. Если бы у нас была не огромная почтовая система, а мини веб-почта, то возможно, эта авторизация бы просто испарилась, уйдя целиком в условие выборки по базе данных (вида "SELECT * FROM
messages
WHEREto_uid
=$user_id"). Это не так красиво выглядит, но в очень простом проекте воспринимается даже проще и органичнее, чем целый класс по проверке прав доступа, с объектами-контенейрами этих прав, и прочими радостями.
Хотя при получении одного конкретного сообщения… Да, думаю, придётся ещё раз проверить, что оно именно наше.
VolCh
12.03.2017 18:11Проблема решений "авторизация бы просто испарилась, уйдя целиком в условие выборки" в том, что при усложнении проекта очень легко можно забыть что это не просто фильтр выборки, но и проверка авторизации. Или наоборот, забыть, что это не просто проверка на наличие прав, но и условие выборки. Лучше уж по умолчанию считать, что авторизации просто нет, чем надеяться на "невидимую".
Такие решения нарушают принцип единственной ответственности и потом сильно усложняют разработку, если закопаны где-то глубоко, либо приводят к дырам типа "Хотя при получении одного конкретного сообщения…"
popov654
12.03.2017 20:43Пожалуй вы правы. Хотя, таким образом можно добиться оптимизации, получив всё в один запрос. Скорость тоже важна.
Это ведь только одно из условий. Их в запросе несколько. Можно написать перед выборкой развёрнутый комментарий. Или сделать понятную документацию к проекту, где будет описано, какая выборка за то отвечает, и наоборот, где у нас авторизация закопана. Ну и плюс тесты, чтобы ни один глюк не просочился… :)
С точки зрения кода отдельно проверка ACL — это лучше. Но боюсь, по производительности это будет не очень айс. Разве что, если у нас запрос всего на один элемент — там скорее всего не так важно, один запрос или два.
lair
12.03.2017 17:38Социальные сети и бизнес-системы — это очень круто, не мой масштаб точно
Есть разница между "не мой масштаб" и "по факту мало где нужно".
Почта — а зачем там авторизация-то? Там обычно один пользователь.
Затем, что там больше одного ящика обычно, и у каждого пользователя доступ к своему ящику. И это не считая администраторов.
popov654
12.03.2017 20:48-1"В мелких проектах мало где нужно", так лучше?) Почта — уже не мелкий проект.
Насчёт ящиков — да, не подумал. Мне почему-то казалось, что вы хотите сделать проверки прав доступа к отдельным письмам в пределах аккаунта.
Ну там опять же это просто логичнее всего сделать дописав ещё один LEFT JOIN к запросу, либо поставив условие на столбец ("WHERE folder_id=1 AND user_id=976"). То есть даже при выборке единичного элемента, если условие на автора не будет соблюдено — вернётся пустое множество строк.
В качестве одного из индексов, кстати, можно сделать составной индекс (user_id, folder_id), при этом глобально в системе id папок могут быть не уникальны, это может быть удобно (например, "Входящие" у всех будут с folder_id=1).
lair
12.03.2017 23:52"В мелких проектах мало где нужно", так лучше?
Не, не лучше. Мелкие проекты бывают совершенно разные.
Ну там опять же это просто логичнее всего сделать дописав ещё один LEFT JOIN к запросу
… и это все равно будет авторизация. Как она реализована — вопрос отдельный.
lair
12.03.2017 16:00+1Дело в том, что этот метод предполагает хранение авторизации в сессиях. Это статья не относится к конкретному языку, и справедлива для любой платформы, но я буду иллюстрировать всё на примере PHP.
… а в asp.net в сессии авторизацию не хранили никогда. И аутентификацию — тоже.
Просто сохраняют в собственной куке айди пользователя. Но поскольку просто айди хранить как-то уж слишком стрёмно (любой может поставить любое число и получить доступ к произвольному аккаунту), то часто вместе с айди за компанию сохраняют и пароль. В открытом виде.
То есть та идея, что в куку надо шифровать на сервере — она слишком сложная и продвинутая? Да, в этом случае остаются атаки через session hijacking, но от них защищаются (дополнительными) одноразовыми токенами (и очень короткой сессией вообще).
Впрочем, я вообще хочу заметить, что сессии и аутентификация — это немножко разные задачи, и не надо их смешивать в одну кучу.
popov654
12.03.2017 16:47Вот про одноразовые токены и про перехват сессий я бы с удовольствием почитал… Я так понимаю, там сервер вместе с каждым запросом выдаёт клиенту новый токен, так? Что будет, если этот токен будет перехвачен вместе с сессией? Злоумышленник делает запрос, потом клиент делает запрос, сервер видит, что такой токен уже был, и закрывает соединение?
lair
12.03.2017 17:40Что будет, если этот токен будет перехвачен вместе с сессией?
… им можно будет воспользоваться ровно один раз, после чего он перестанет быть валиден.
popov654
12.03.2017 20:14И может так оказаться, что им воспользуется перехвативший, а клиент получит отлуп. Не очень здорово как-то же?
lair
12.03.2017 20:19+1… зато в симметричном случае отлуп получит перехвативший, и мы не получим, например, лишнюю транзакцию с карты. Пусть даже в одном случае из двух — все равно неплохо.
Вообще, (почти) любая защита ведет к понижению комфорта пользователя, это нормально. Неприятно, но неизбежно.
popov654
12.03.2017 21:10Только я боюсь, что перехвативший сделает транзакцию на свою карту в этом 1 случае из 2. Точнее, сделал бы, не будь смс-подтверждения :)
Я скорее это имел в виду, а не то, что неудобства появятся.lair
12.03.2017 23:56Только я боюсь, что перехвативший сделает транзакцию на свою карту в этом 1 случае из 2
Если, как и полагается с sensitive-данными, делать подтверждение с нормальным хэшом, не выйдет. Одноразовые токены нужны для защиты от реплея.
Ну и да, один случай из двух лучше, чем два из двух.
ArsenAbakarov
12.03.2017 16:14+2"Надёжная авторизация для веб-сервиса за один вечер"…
«Как выучить с++ за 21 день — купить большую рыбу и ударить себе по лбу»
dvserg
12.03.2017 16:39А в дополнение к… — в направлении использования шифрования с открытым ключом не думали? По крайней мере от сниффинга вайфай вполне может помочь (но не от MITM).
popov654
12.03.2017 17:01Пока не думал. Я так понимаю, схема такая: клиент генерирует свой закрытый ключ, сообщает серверу открытый к нему, и сервер использует его для расшифровки трафика от клиента? Вообще вариант. Не подскажете, какими штатными средствами такое реализуется? Это будет тот же самый SSL по сути, только с клиентским сертификатом?
dvserg
12.03.2017 21:09Лучше наоборот, сервер передаёт клиенту открытый ключ сессии для шифрования информации при передаче данных аутентификации клиентом. Сниф таких зашифрованных данных и знание ключа ничего не даст, т.к. ключ несимметричный (кроме МИТМ).
brevis
12.03.2017 17:42+2Смотри как пишут «Hello, World!» на PHP в 2017м :)
Вот ты тоже про аутентификацию в таком ключе напиши. Тоже будет о чем поговорить :)popov654
12.03.2017 17:53О май гад. Мне кажется, или в 1998-ом всё было сильно проще (даже при том, что не было даже пятёрки ещё)?
Имхо, надо соразмерять задачу и используемые средства, и не стрелять из пушек по воробьям.
brevis
12.03.2017 17:55В 1998 я играл в условную «Денди».
Сейчас играют в программирование :)popov654
12.03.2017 18:18Я не о том. Я про то, что на старте (хотя сам кодинг что на PHP, что на JS был несколько сложнее из-за отсутствия удобных фич и глюков браузеров, если говорить о клиентском коде) не было всей этой мути. И жить было сильно проще. Ведь как посмотришь псевдо-коды, который используются во всех этих шаблонизаторах и хитрые закрученные схемы взаимодействия этого всего — волосы дыбом встают. Намного ведь лучше писать простой и приятный код, который легко читать и отлаживать, и который предсказуем. Над которым не надо ломать мозг. Так зачем это всё? :)
Я когда-то думал, что jQuery местами слишком упрощает жизнь программисту; потом я думал, что она добавляет сложности, поскольку кроме чистого JS надо помнить её методы, особенности их работы, какой и когда лучше использовать. Теперь, глядя на этот трэш, я понимаю, что jQuery-то просто сама няшность по сравнению со всем остальным.
m0Ray
12.03.2017 19:09+1Вот именно — современные инструменты дают возможность писать простой и легкочитаемый код, который удобно отлаживать. Иногда в ущерб производительности, но далеко не всегда.
Жить тогда было не сильно проще. Я начинал с PHP 3.3 и ещё помню этот ужас, когда кучу вещей приходилось каждый раз делать руками. И всё равно получалось дыряво, и ночами сидел, искал глюки, отлаживал… Сейчас всё намного проще, надо просто чуток поменять подход и не парсить, скажем, HTML при помощи регулярных выражений, а задействовать соответствующие библиотеки. Ну, конечно, разобраться надо поначалу, как этой библиотекой пользоваться, но потом же — красота и лёгкость бытия.
Да, есть жуткие проекты типа WordPress, в которых чёрт ногу сломит. Так не пользуйтесь ими, никто ж не заставляет.
Взять тот же jQuery — я его просто обожаю. Вместо десятиэтажных конструкций на голом JavaScript — один-два вызова jQuery. И не сказать опять же, что это тормозит. У них и девиз соответствующий: do more, write less. Элементарно сравнить:
document.getElementById("#someId").innerHTML="someValue";
и
$("#someId").html("someValue");
Я уж молчу про сложные случаи с AJAX или манипуляцией DOM.
За вас написали огромное количество boilerplate кода, а вы ещё и нос воротите. Не понимаю.VolCh
12.03.2017 19:28Да, есть жуткие проекты типа WordPress, в которых чёрт ногу сломит.
Добавлю, что зачастую жуть таких проектов обусловлена именно отсутствием в то время инструментов подобных современным и желанием/необходимостью тянуть и сейчас лямку обратной совместимости с принятыми тогда "лучшими" решениями. Может код того же WordPress несовместим сейчас даже с 5.3, но архитектура его хорошо если по лучшим практикам 4.0 построена.
m0Ray
12.03.2017 19:53Нет, он вполне совместим, даже на 7-ке запускается. Костыли туда впиливают оперативно.
Но это именно что костыли. Я, когда вирусы лечу на сайтах с этим движком, регулярно в код заглядываю. Там чёрт знает какие практики на самом деле.
Ну а отсюда и дырявость, и прочий ужас безысходности при словосочетании «написать модуль».
А вообще согласен: тянуть обратную совместимость со старыми решениями нередко бывает непродуктивно. Хоть это и болезненно для разработчика, смена парадигмы иногда бывает необходима.
popov654
12.03.2017 19:56Не вижу, чем первый вариант хуже. Работает к тому же чуть быстрее. Дольше печатать — ну так Ctrl+C/Ctrl+V никто не отменял :)
От библиотек, облегчающих работу с DOM/XML/изображениями/чем угодно на сервере я нос не ворочу. Вовсе нет. Я про тот код, что по ссылке, которую brevis скинул выше. Вот это у меня язык не повернётся назвать читаемым :) jQuery я наоборот похвалил в комментарии выше за чрезвычайную человекопонятность.
И всё равно получалось дыряво, и ночами сидел, искал глюки, отлаживал
Это PHP был так плох? У меня нет сильных глюков, и всё не так дыряво (в основном), при этом я пишу едва ли не в стиле PHP4, ну разве что всякие суперглобальные масссивы и глобальные переменные (когда $_GET и $_POST автоматом в переменные разворачиваются) не использую. И я бы не сказал, что очень тяжело, и много отладки. Бывают глупые синтаксические ошибки, но в новой версии ISP Manager есть подсветка синтаксиса и синтаксический анализатор кода на JS. Там все ошибки подчёркиваются мгновенно, так что ошибиться стало просто негде. Ну и плюс внимательность.
Более того, если писать код в ООП стиле, шансов накосячить ещё меньше.
m0Ray
12.03.2017 20:23Он хуже как по читаемости, так и по переносимости. Работает оно если и быстрее, то вряд ли это можно заметить на практике.
Чтобы сделать Ctrl+V, надо сначала найти кусок, где надо сделать Ctrl+C. А когда код вот из-за таких десятиэтажных конструкций раздут, будете очень долго искать.
Что касается кода по ссылке — я его вообще читал как стёб или троллинг. Программистский юмор бывает весьма своеобразен.
Был плох не то чтобы PHP, не было ещё выработано хороших практик, библиотек, фреймворков. ПисАть свою CMS на костылях и велосипедах с нуля было в порядке вещей. А потом из-за этого вылезало такое, что хотелось плакать и переписать всё с нуля опять. У меня с одной такой CMS итераций пять было, когда просто всё бросали и переделывали заново, ну или почти заново.
В процессе становления у любого ЯП есть «детские болезни», и PHP не исключение. Но сейчас-то, когда всё более-менее устаканилось, зачем возвращаться к костыльным временам? Из-за того что они тёплые и ламповые? Для меня это не аргумент.
Взял фреймворк, усвоил философию и стиль кода — и поехал вперёд, не отвлекаясь на мелочи. Потому что в этом случае за вас уже сделали много рутинной работы. Осталось только отписывать логику проекта.
Я вижу, как у вас не дыряво. Забыли вставить функцию экранирования, и… Тут синтаксическая подсветка не спасёт.popov654
12.03.2017 20:59Со мной такое редко, поверьте) Числовые значения я привожу к int, а строковых у меня мало, когда они и встречаются — сначала делаю проверку на формат, прежде чем что-то в базу писать.
Насчёт ламповости — ну я это время как-то не застал, мне в 98 ещё 6 лет всего было :)
Взял фреймворк, усвоил философию и стиль кода — и поехал вперёд, не отвлекаясь на мелочи.
Так в том-то и дело, что писать свой фреймворк, постоянно его развивая — это не мелочи. И это очень интересно. Кстати, именно так вырос первый Symfony, по словам авторов книги (самих разработчиков).
Чтобы сделать Ctrl+V, надо сначала найти кусок, где надо сделать Ctrl+C. А когда код вот из-за таких десятиэтажных конструкций раздут, будете очень долго искать.
Да, бывает тяжко. Но обычно мотать не очень далеко, у меня таких конструкций повсюду тонны.
Он хуже как по читаемости, так и по переносимости
Читаемость — таки во многом вопрос привычки (да и кто вам мешает сделать короткий шорткат, как сделал разработчики вк, ge('id')?
А с переносимостью ровно наоборот. Ваш вариант требует тащить за собой jQuery (хоть она в минифицированном виде и не так много весит). Плюс новые версии jQuery имеют свойство не работать в очень старых браузерах. Мой же код не будет требовать сторонних библиотек и будет работать почти везде. Почти — потому что со старыми IE всё сложно, к сожалению. Но даже там код на чистом JS исполнится хоть как-то с гораздо большей вероятностью, если совсем повезёт — то вообще без ошибок).
MikailBag
12.03.2017 21:04+1Но зачем Вам нужен IE5? (jQuery 1.12: "Internet Explorer 6-8, Opera 12.1x or Safari 5.1+").
Ваш код полностью потонет в костылях.
m0Ray
12.03.2017 21:42+1Дело не в том, насколько у вас там что редко. Дело в том, что вы используете тёплый ламповый подход, который требует вручную разруливать все эти мелочи и позволяет ошибаться. Сравните с подходом, который я продемонстрировал с mysqli — о такой мелочи, как экранирование и приведение типов к нужному, мне заботиться уже не надо. То же самое с PDO.
Похожие явления наблюдаются со многими другими современными практиками, которые вы упорно отвергаете: меньше вероятность ошибки, меньше требуется внимания к мелочам, больше времени ресурсов можно сосредоточить на бизнес-логике. За вас уже подумали, вам уже сделали хорошо, даже включили кое-что в стандартную поставку языка.
Но нет. Вы гордые. И думаете, что костыли будут быстрее и надёжнее «сегвея» — просто потому что выстругали их сами.
Если у вас невероятно уникальная задача, под которую надо писать свой фреймворк — ну тогда да. Только если этот фреймворк будет везде содержать тонны спагетти-кода — я, пожалуй, лучше какой-нибудь другой использовать буду.
Что касается переносимости и совместимости — у jQuery 1.x отличная совместимость со старыми браузерами, вероятность запуска кода с ним гораздо выше, чем без него. Об этом, к примеру, тут ясно написано.
Я уж молчу о поддержке мобильных устройств и т.п. Сколько костылей вы наваяете на голом JS для этого и как это будет работать — мне представить сложно.popov654
15.03.2017 19:27То-то я смотрю у меня 70-80 процентов сайтов, сделанных на фреймворках, не работает в Opera 11 и даже 12 (про IE 8 я вообще молчу). Не, я верю, что виноват не фреймворк, а плагины к нему (которые не настолько кроссбраузерны). Но когда используешь фреймворк, обвешать проект плагинами — уже очень велик соблазн. Потому что если всё пишешь сам — зачем фреймворк тогда :)
SerafimArts
15.03.2017 19:37То-то я смотрю у меня 70-80 процентов сайтов, сделанных на фреймворках, не работает в Opera 11 и даже 12
Попробуйте открыть из MS DOS. Я думаю это решит вашу проблему. Если не получится — можно попробовать со спектрума...
popov654
15.03.2017 19:53К чему этот троллинг? Я ответил на конкретную цитату. Со слов разработчиков, поддержка jQuery "Internet Explorer 6-8, Opera 12.1x or Safari 5.1+".
Так вот, по факту в IE8 не работает уже даже и 10 процентов сайтов корректно. А Opera 11, хотя технически гораздо совершеннее, отсутствует в этом списке даже официально. При чём тут "Спектрумы", если речь про браузер 2012-ого года релиза?.. 5 лет не прошло ещё даже.
SerafimArts
16.03.2017 00:18Это просто ответ и вам и автору коммента выше. Наверное надо было его тоже упомянуть. Сабж ( m0Ray ) не знает о транспайлерах под JS, а вы ведётесь и предлагаете проверять в том, что никто не использует указанные 5 лет (если не больше).
Примерно как с вашим кодом из начала двухтысячных =) Сами себе буратино, что ещё можно сказать.
VolCh
15.03.2017 20:13Я напишу код без всяких фреймворков и библиотек, который не будет работать в старых Операх и ИЕ, не поддерживающих хотя бы на 90% ES2015. Простейший код типа const str = 'test'; alert(str); Так что фреймворки тут не причём, это обычно сознательное решение разработчика отказаться от совместимости со старьём. Под фреймворки, библиотеки и плагины ограничивают совместимость только "снизу", а разработчик ограничивает её "сверху".
popov654
16.03.2017 04:55Не очень вас понял, что значит "снизу"? Фреймворки же не ограничивают никого в использовании новых функций. Про ES2015 я вообще очень недавно узнал, кстати. Да, такой код работать не будет, если его специально не сконвертировать каким-то образом в пригодный.
И имхо это не очень хорошо. У людей могут быть причины использовать старый браузер, а у них ломается две трети интернета :)
VolCh
16.03.2017 05:34jQuery, например, поддерживает IE6-8 — если в проекте используется jQuery, то на IE5.5 он вряд ли запустится. Это ограничение снизу. Но если в коде проекта есть const, то работать не будет и в IE10, только в IE11 — это ограничение сверху. Правильней будет, конечно, поднятие ограничения снизу разработчиком по сравнению с фреймворком.
VolCh
12.03.2017 18:20В 1998-м ещё даже четверки не было (как сейчас помню — какого-то нового Президента РФ вроде выбрали, а я выход PHP 4.0 RC ждал), то есть никакого ООП вообще, и, тем более, инструментов, сравнимых хоть как-то с Symfony, Doctrine, React и т. п., позволяющих почти сразу переходить к бизнес-логике, а не заниматься инфраструктурніми задачами, переходящими из проекта в проект.
popov654
12.03.2017 20:09Имхо, можно основные задачи решить единожды и дальше таскать тупо из проекта в проект. Ну или накодить заново, если не лень. Та же паджинация, например, в простейшем случае пишется минут за 15-20.
Ну так юмор ситуации в том, что многие не используют ни React, ни Symfony, ни даже ООП. А просто пишут код, который работает.
На самом деле, часто даже функции бывают лишними: если кода очень мало, можно часть вынести во внешние файлы и подключить в шаблон (в этих файлах можно создать одну или несколько функций как раз), ещё часть файлов будет служить точками получения данных из базы (в JSON или HTML, либо комбинированный вариант в зависимости от параметров), а всё остальное — это просто шаблоны, то есть HTML с вкраплениями PHP, и JS даже бывает удобно размещать прямо там же, когда его не очень много.
То есть нет даже такой задачи, ради которой требовалось бы писать много чистого кода, бизнес-логики в вакууме — в отрыве от HTML, баз данных, переменных HTTP-запроса и прочего.
lair
12.03.2017 20:25+1То есть нет даже такой задачи, ради которой требовалось бы писать много чистого кода, бизнес-логики в вакууме — в отрыве от HTML, баз данных, переменных HTTP-запроса и прочего.
Вы забыли важную оговорку: у вас нет "такой задачи, ради которой..."
m0Ray
12.03.2017 20:35Зачем писать паджинацию каждый раз, если её уже раз надцать написали в разных фреймворках? Чтобы иметь больше шансов накосячить в очередной раз?
Код фреймворка обычно вычитан и вылизан немалым количеством программистов. А кто вычитывает и тестирует ваш код перед тем, как он попадёт в продакшн?
Да, я не использую React и Symfony сами по себе. Я использую Drupal 7, который сам по себе неплохой фреймворк со встроенной CMS, и Drupal 8, который основан на Symfony. Знаете, отлично всё работает, да ещё и написать новую логику получается очень быстро. Нужда в велосипедах у меня теперь возникает крайне редко.
Смешивать всё в кучу — плохо, очень плохо. Это сначала кажется, что так проще, потом же, в процессе разработки, всё это превращается в ужасный кусок кашеподобного кода. Его очень сложно поддерживать, отлаживать, изменять. Гораздо лучше сразу отделить мух от котлет и по мере усложнения разбивать на всё более мелкие части. Потом, при отдаче пользователю, всё это склеивается фреймворком и кладётся в кэш, чтобы потом уже не надо было ничего клеить. В производительности таким образом вы не теряете практически ничего, а в читаемости и лёгкости поддержки — очень много.
Вы что, пишете только мелкие, одноразовые задачки? Ваши проекты не растут, не развиваются, не живут долго?popov654
15.03.2017 19:32Это сначала кажется, что так проще, потом же, в процессе разработки, всё это превращается в ужасный кусок кашеподобного кода. Его очень сложно поддерживать, отлаживать, изменять.
На каком-то этапе так, к сожалению, бывает. Но не всегда. И обычно на этот момент все фичи уже написаны и новые не добавляются. Только исправляются ошибки.
Вы что, пишете только мелкие, одноразовые задачки? Ваши проекты не растут, не развиваются, не живут долго?
Вообще, видимо так, вы правы. Ну как недолго — год-два максимум. И да, задачки не настолько крупные :)
silentrs76
12.03.2017 19:57+4Прочитав статью и комментарии такое ощущение, что автор в пещере лет 10 прожил и недавно вышел оттуда.
popov654
12.03.2017 20:02Почему в пещере? Автор, с вашего позволения, с 2007 года пишет на PHP проекты разной сложности. Примерно с 2012-ого года более-менее серьёзные. И про ООП знает, и даже читал про позднее статическое связывание (правда не очень понял). И про трейты в курсе. И cURL, GDlib, DomParser и ещё пару расширений юзал. И даже по Symfony 3 немного читал учебник. Зря вы на автора гоните :)
lair
12.03.2017 20:21+4даже читал про позднее статическое связывание (правда не очень понял)
Ну, хоть честно.
popov654
12.03.2017 21:16Мне тогда показалось, что даже в Java это всё как-то попроще устроено. Плюс в самом же мануале и в чейнджлогах есть оговорки, что поведение PHP от версии 5.2 к версии 5.4 весьма сильно менялось в этих моментах… Вплоть до того, что при доступе к элементам через определённый синтаксис можно было получить один элемент, либо другой элемент, либо ошибку. Вроде касалось это как раз статических методов и наследования.
SbWereWolf
13.03.2017 08:41в коментах не увидел ни одного принципиального возражения против подхода автора, все замечания к реализации, то есть идея ок?
lair
13.03.2017 12:40А вы можете коротко и непротиворечиво сформулировать эту "идею"?
SbWereWolf
13.03.2017 13:05хранить в куках кроме пхп_сессии какие то данные для валидации это самой сессии, и если данные в сессии отличаются от реальных ( например юзер агент сохранённый в сессии отличается от юзер агент в запросе), то считать такой запрос не валидным и направлять на страницу авторизации.
Для «хардкорности» можно юзер агент и другие данные в куках каким то образом шифровать, что бы взломщику было не понятно как подобрать хак.
я так понял идею автора.VolCh
13.03.2017 13:29В целом идея автора — создать свой механизм "запомнить меня в этом браузере" и реализовать привязку к IP/UA/другой "секретной" технической информации.
lair
13.03.2017 13:37Давайте разобьем на две части.
Использовать для валидации сессии не только идентификатор сессии, но и другие данные. Идея не новая (та же привязка к IP регулярно встречается). Тут вопрос в том, какие именно данные использовать — потому что, как мы понимаем, если я смог перехватить куку, то что мне мешает заодно и юзер-агент перехватить? А привязываться к IP нельзя по уже описанным причинам.
- Где хранить "другие данные" — в куке или где-то на сервере. Это просто компромис между "что нагружать" — клиент и канал или сервер. Ну и да, данные, хранящиеся на сервере, немного сложнее подменять/анализировать.
SbWereWolf
13.03.2017 14:14по вашей оценке, идея здравая или лучше не надо? пожалуйста, без относительно реализации.
lair
13.03.2017 14:31+1"По моей оценке" это старая идея, имеющая много недостатков. Лучше брать готовые реализации.
SbWereWolf
13.03.2017 14:49в смысле из какого либо фрейворка «модуль» «подключить»?
lair
13.03.2017 14:50+1… или просто модуль, без фреймворка.
SbWereWolf
13.03.2017 15:26если с фреймворками понятно где взять, а с модулями может быть подскажите источник наименований модулей? ( про гугл я уже догадался )
lair
13.03.2017 15:07Собственно, вот тут все уже написано, раздел "Binding the Session ID to Other User Properties":
With the goal of detecting (and, in some scenarios, protecting against) user misbehaviors and session hijacking, it is highly recommended to bind the session ID to other user or client properties, such as the client IP address, User-Agent, or client-based digital certificate. If the web application detects any change or anomaly between these different properties in the middle of an established session, this is a very good indicator of session manipulation and hijacking attempts, and this simple fact can be used to alert and/or terminate the suspicious session.
Although these properties cannot be used by web applications to trustingly defend against session attacks, they significantly increase the web application detection (and protection) capabilities. However, a skilled attacker can bypass these controls by reusing the same IP address assigned to the victim user by sharing the same network (very common in NAT environments, like Wi-Fi hotspots) or by using the same outbound web proxy (very common in corporate environments), or by manually modifying his User-Agent to look exactly as the victim users does.popov654
15.03.2017 19:59Ну вот про это была и вся моя статья, по сути. И там кстати было сказано, что это не панацея. Что и подтверждает второй абзац Вашего текста :)
lair
15.03.2017 23:06… а если это не панацея, и при этом HTTPS от всей этой белиберды защищает, то зачем возиться?
popov654
16.03.2017 04:49-1Например потому, что есть куча горе-стартапов (либо личных бложиков), у которых даже нет денег на сертификат. Ну или жаба душит)
lair
16.03.2017 11:40+1После 12 апреля 2016 года отсутствие денег не является оправданием отсутствия HTTPS.
(да и до того были варианты вполне себе)
popov654
15.03.2017 19:46Привязываться к IP можно, реальное использование этого кода доказало, что неудобств это не вызывает (напротив, позволяет как side-эффект фиксировать каждую смену IP-адреса).
Ну и главный плюс этой схемы, о котором все комментирующие забыли — возможность сделать инвалидацию (принудительное закрытие) любой сессии. Что при коде вида
if (!isset($_SESSION['user_id'])) { /* redirect to auth.php */ }
сделать нормально практически невозможно. Пjтому что простым образом сбросить можно только свою сессию, но не чужую :)
lair
15.03.2017 23:06Привязываться к IP можно, реальное использование этого кода доказало, что неудобств это не вызывает
У кого не вызывает? У человека, который с планшетиком переходит от вайфая к вайфаю?
Ну и главный плюс этой схемы, о котором все комментирующие забыли — возможность сделать инвалидацию (принудительное закрытие) любой сессии.
Это плюс не вашей схемы, это плюс привязки сессий к пользователю. Которую привязку можно делать на сервере прямо в хранилище сессий.
TicSo
15.03.2017 19:32Интересная тема.
Прошу автора написать статью с учетом правок и новых идей, в идеале, на php 7.1.
Может кто подскажет, как правильно организовать следующее:
- есть сайт, условно site.com
- есть форма входа/регистрации, возможно, с капчей
- зарегистрированный пользователь получает своё 'поле деятельности', например, индивидуальную схему в базе данных postgresql
- для пользователей (как разовых, так и зарегистрированных) заложена система
push_уведомлений (подписка),…, чат ...
1. Сайт предоставляет функционал как для зарегистрированных пользователей, так
и для разовых (точнее, разовый == не зарегистрированный).
2. Пользователь, имеющий регистрацию, может зайти на сайт, но не пройти авторизацию,
и действовать по правилам разового.
Возможно, есть ещё вариации, или моменты на которые нужно обратить внимание.
Как разграничить задачи сессий и аутентификации и правильно организовать функционал такого сайта?
Чтобы был учет всех посетителей, их статусов, ip, действий… попыток взлома…
Подскажите, пожалуйста, лучшие практики.
VolCh
15.03.2017 20:40Открывать сессию при заходе на сайт, сохранять всё что нужно/можно, при успешной аутентификации сохранять в сессии id пользователя, при доступе к общей функциональности писать логи доступа с данными сессии, анализировать на подозрительную активность и т. п., если что блокировать по сессии (записать в сессию признак блокировки), при доступе к закрытой функциональности блокировать не только сессию, но и учетку пользователя.
LeMaX
15.03.2017 19:34+1Я такой код только в 4 ветке видел, эх ностальгия.
Ну и по теме…
Забыли про XSS, CSRF, данный код от них ну никак не защищает/предохраняет/перекрывает/прекрывает и т д.
mysql_real_escape_string не панацея, а использование данной функции для фильтрации входящих целых чисел вообще добавляет уязвимость, в особенности если память не изменяет, то в кодировках SHIFT_JIS, BIG5, GB2312, EUC-JP, EUC-KR (мультибайтовых, utf8 не подвержен вроде как, хотя видел случаи с ним). Так же не стоит забывать, что функция mysql_real_escape_string не учитывает кодировку соединения(насколько помню на момент 2006 года), потому надо не забыть проставить mysql_set_charset()… Именно эта функция пакета mysql должна использоваться должна использоваться для выставления клиентской кодировки вместо запроса SET NAMES.
md5 давно уже не рекомендуется к использованию, если память не изменяет, то автоматизировали поиск коллизий по алгоритму md5 еще в 2006 году. Не зря от него отказались git в пользу sha1, так же sha1 широко используется не только в контроле версий но и в системах подписи… Да куда уж тут ходить, sha1 находится в основе SHACAL, что так же добавляет к нему доверие… За исключением гугла, они в него верить перестали :D
Насчет передачи айди. Все известные системы wp, bitrix, dle используют аналогичный подход(единственное он более совершенен в плане хранения) и где автор видел подход функции «запомнить» с передачей в куку только айди пользователя — не могу понять, вроде такая проблема была в php nuke, но уже столько воды утекло, что даже и представить не могу кто его еще использует О_о…
Так же во многих комментариях проскальзывало про mysql_* функции… С 2006 года весь пакет mysql находился в состоянии discouraged, потому что небыло человека который бы им занимался, а сообщество уже активно рекомендовало использовать mysqli расширение. Само расширение mysql вылетело в статус deprecated только с ветки php 5.5… Собственно не удивительно, ведь текущая разработка интерпретатора ведет и к постепенному выпиливанию mysqli расширения в пользу PDO.
P.S. Тем кто не верит в CSRF, она реальна и в последние годы набирает обороты в использовании. Не зря во всех популярных фреймворках идут встроенные методы защиты для передаваемых форм.popov654
15.03.2017 19:39Спасибо за развёрнутый комментарий.
Забыли про XSS, CSRF, данный код от них ну никак не защищает/предохраняет/перекрывает/прекрывает и т д.
Это тема отдельной статьи. Тем более, согласитесь, CSRF актуален далеко не только на этапе авторизации :)
md5 давно уже не рекомендуется к использованию
Но всё ещё много где используется, хотя возможно, это не есть хорошо. В целом я не настаиваю на использовании именно md5, можно заменить на любую другую хэш-функцию.
С 2006 года весь пакет mysql находился в состоянии discouraged, потому что небыло человека который бы им занимался, а сообщество уже активно рекомендовало использовать mysqli расширение
Знаю об этом. Но всё же это не делает его использование катастрофой, я полагаю.
а использование данной функции для фильтрации входящих целых чисел вообще добавляет уязвимость, в особенности если память не изменяет, то в кодировках SHIFT_JIS, BIG5, GB2312, EUC-JP, EUC-KR
Целые числа я ей не фильтрую, к счастью.
Так же не стоит забывать, что функция mysql_real_escape_string не учитывает кодировку соединения(насколько помню на момент 2006 года), потому надо не забыть проставить mysql_set_charset()… Именно эта функция пакета mysql должна использоваться должна использоваться для выставления клиентской кодировки вместо запроса SET NAMES.
Расскажите, пожалуйста, подробней, почему так. Я использую именно SET NAMES в силу простоты этой команды. Если это опасный подход — хотелось бы понять причину.
Насчет передачи айди. Все известные системы wp, bitrix, dle используют аналогичный подход(единственное он более совершенен в плане хранения) и где автор видел подход функции «запомнить» с передачей в куку только айди пользователя — не могу понять
Ну видите, уже поэтому этот подход нельзя назвать "вредным советом". Насчёт "только айди" — это было скорее в плане шутки. Ну знаете, человек, который пишет первый в жизни Hello World, может не знать, что айди в куке — это никакая не защита. Не тот ресурс я выбрал для такого капитанства, согласен. Хотя… вдруг кто-то в поиске нагуглит :)
SerafimArts
16.03.2017 00:25Но всё ещё много где используется, хотя возможно, это не есть хорошо. В целом я не настаиваю на использовании именно md5, можно заменить на любую другую хэш-функцию.
А может лучше воcпользоваться встроенными в php? Почитать manual по php, где чёрным по белому написано, что md5 использовать нельзя. А потом открыть ещё одну страничку, где есть встроенная в язык функция для хеширования паролей? Думаю всё же не глупые люди всё это писали =)
popov654
16.03.2017 04:09Ну раз авторы языка рекомендуют, я спорить с ними не буду =)
Однако хочу заметить, что данная функция появилась лишь в версии 5.5, то есть относительно недавно. А раньше юзали md5 ещё как — очень многие CMS тому пример. Хотя, конечно, были и альтернативы: Blowfish, SHA1.
Мне впрочем раньше казалось, что Blowfish — алгоритм симметричного шифрования, а не хэширующий. Надо будет погуглить ещё раз.
popov654
16.03.2017 04:42Хотя, если совсем честно — я бы поставил эксперимент. Поскольку я не имею знаний в области криптографии, а также практического опыта по взламыванию чего-либо, трудно просто так взять и поверить на слово, что алгоритм уязвим. У меня конечно далеко не самое мощное железо, но я бы мог выделить часть ресурсов на своём домашнем сервере на 2-3 месяца с той целью, чтобы попытаться вскрыть хотя бы один MD5 хэш. Если за это время ничего не выйдет — надо полагать, использование алгоритма не так опасно, или я ошибаюсь?
andreymal
16.03.2017 09:47Такие вещи делают не на «домашнем сервере», а в каких-нибудь амазоновских облаках за небольшую (вроде) плату. А там это займёт всего 2-3 недели)
Zhuravljov
16.03.2017 10:26Фрагмент из доклада про безопасность веб-приложений https://youtu.be/_i1d9M40-qc?t=1030. Там, в числе прочего, про то, почему для паролей MD5 использовать опасно.
LeMaX
16.03.2017 09:54Насчет SET NAMES, это я помню еще по временам снова таки php 5, а именно это писалось и в документации к самому mysql расширению(http://php.net/manual/ru/function.mysql-set-charset.php), а так же по кодировке символов соединения (http://php.net/manual/ru/mysqlinfo.concepts.charset.php), ну и в догонку в самой документации по функции mysql_real_escape_string(http://php.net/manual/ru/function.mysql-real-escape-string.php) так же описано про использование встроенной функции установки кодировки. Плюс, суть работы функции mysql_set_charset является установкой клиентской кодировки(т.е. кодировки самой библиотеки клиента, плюс соединения с бд), в то время как SET NAMES устанавливает только session_set_client, character_set_connection и character_set_results, и помойму еще collation_connection в сортировку для указанной кодировки.
Так же если обратится к самой документации mysql, а именно к C API методу mysql_real_escape_string. Так же существуют предупреждения насчет SET NAMES — https://dev.mysql.com/doc/refman/5.5/en/mysql-real-escape-string.html
Вроде ничего не упустил.
Varim
sql injection
popov654
Спасибо, и правда глупо получилось)