Pull to refresh

Comments 68

При такой авторизации никакой безопасности нет. Подменив куки я войду под любым пользователем, толку от нее тогда?

Я вам скажу из своего опыта, что любой человек, уже привык что-то вводить, нажимать итд. Я недавно делал калькулятор на яваскрипте, и ради эксперимента убрал кнопку рассчитать, завязал функцию за смену содержимого в текстбокс, так вот, прошло пол года, и было очень много людей, которые даже при мне искали эту кнопку.
Я уже писал, напишу еще, на мое мнение нужно требовать от пользователя регистрации/авторизации только в случаях необходимости, как вы писали, например, голосования, комментариев итд. Я бы просто спрашивал логин и пароль, логин это мейл. После ввода данных оно проверяет наличие мейла в базе, если нет, сразу регистрирует (можно спросить, мов, мейл пупкин не найден, зарегистрировать?) и дублировать данные ему на почту (так как пароль введен 1 раз пользователь мог опечатается). Вот и вся процедура, если вам нужен адрес, пожалуйста, спросите его когда скажем пользователь хочет что бы ему доставили товар, спросите, «А куда вам его доставить»? После ввода вы получили данные, а пользователь ожидал этого вопроса, это интуитивно понятно и не сложно. Таким же образом можно получить и другие данные.
Подменив куки где угодно вы войдете под любым пользователем. Это совершенно естественно. И надо не отказываться от куки а усиливать аутентификацию — например собирать статистику по ip и если вдруг внезапный вход с другого ip — высылать письмо, требовать подтверждения или еще что-то. Кука шифруется, у нее есть таймаут и всякие дополнительные данные о пользователе, но она все равно остается кукой — т.е. неким «секретом» между пользователем и сервером.

И вы вряд ли сможете аутентифицировать (без сложных плясок с бубном в которых все равно возникнет общий секрет) пользователя, который не способен сообщать вам какие-либо «секреты», т.к. он ничем не отличается от произвольного анонимуса — у того тоже нет «секрета»
Если про куки вы написали верно, то ваша идея по поводу обслуживания входа с другого IP — бред. Т.е. мобильные пользователи будут постоянно подтверждать новые ip, с которых они входят? :)
Gmail ведь предупреждает о новых непонятных посещениях, но не препятствует. А мобильные браузеры отслеживаются по User-Agent, в конце концов.
Вы в facebook с других компьютеров или в in-private режиме заходили? Каждый раз предлагается дать имя компьютеру и на ваш email высылается письмо — «в ваш аккаунт зашли вот такие-то, если это не вы — перейдите по линку х».

Я не говорю что надо применять все меры и сразу, но защищать авторизацию по куки надо не методом «отказа от авторизации по куки».
И fb и vk, насколько я знаю, следят за входом с IP из других стран (насчёт регионов не уверен, но тоже может быть) — в отпуске пришлось подтверждать что я это я, добивая заключительные цифры номера телефона. Если следить за каждой сменой IP то это действительно больше похоже на паранойу.
Зайдите в фб в приватном режиме — ip ваш, все ваше, только нету никаких следов FB
1. А как Вы куку подмените? На что? Даже зная нужное значение (ведь совсем необязательно хранить id пользователя в чистом виде), в куке лучше хранить хэш. В Kohana куки записываются по интересной схеме — первая часть — хэш (по ключу), а вторая — чистое (исходное) значение куки. Так что прочитать можно, а вот подменить маловероятно.

Опять же, наиболее критичные участки надо все равно прикрывать принудительной авторизацией, об этом я писал.

2. По поводу запроса личных данных — ничего требовать и не надо! Если пользователь захочет, он введет. Мое дело — сообщить ему о том, как и где он это может сделать. Сам не люблю многостраничные портянки, которые надо заполнять при регистрации. Буээ
Kohana куки записываются по интересной схеме — первая часть — хэш (по ключу), а вторая — чистое (исходное) значение куки.
Интересная схема называется электронная подпись :)
Ну, интересная она в сравнении с обычними, незащищенными куками :) Так-то да, signed cookies и есть.
Хмм. Сейчас в проекте уже реализовали подобное разделение и глянув на ваше описание — увидел все камни которые мы обошли. Итак (сейчас будет не претензия на истину, а немного другой взгляд на вещи):

1. Users — странная таблица. У нас тоже была изначальная идея как и в предложенной схеме, но потом стало понятно, что с реализацией «мультивхода» она выглядит неправильно. Итак у нас это Profile.User и сущность там, на самом деле, профиль пользователя, т.е. то, что касается пользователя у вас на сайте. И email слабо относится к этим данным (подробности позже). Т.к. у нас система распределенная — UserID у нас Guid, но в общем это не сильно относится к делу. ах да, и никакого «главного логина» — это знание логина, а не профиля

2. Auth_data (Credential) — вот самое интересное. У профиля для входа может быть несколько креденшиалов, но вот профиль не знает ничего про сайты или вход, ну не его это дело — знать. Поэтому тут разворачиваем связь в виде Profile->Сredential, т.е. у каждого Credential есть UserId, email (т.к. у каждого сервиса может быть разный email =), fb например позволяет анонимизировать почту при предоставлении аутентификации), еще флаговый признак — IsPrimaryEmail ( понятно для чего — «главный логин» он же «основной email»), тип креденшиала — google, Facebook, twitter, plainpassword, признак верификации (т.к. нам критично получить валидный email — для plainPassword мы высылаем ссылку-подтверждение email) ну и любимый всеми хомячками auth_data в XML формате ( с ней пока не работаем, но планируем).

Ключевой момент при проектировании бд — правильно отделять «мух от котлет», и то, что на первый взгляд «да ну, не страшно что продублируем информацию», потом обернется серьезными переделками. Если вы хотите иметь другую логическую структуру в бд («запросы писать удобней» или «так понятней») — сделайте удобный набор view. Но физическую структуру правильней разделять на независимые и конкретные сущности.

3. При входе через провайдера — мы извлекаем email и ищем совпадения в БД, если есть совпадение с каким-то подтвержденными credential — привязываем новый вход уже к известному юзеру и добро пожаловать. Если совпадения нет — возникает выбор — «создать новый и войти» (одна кнопка) или ввести пароль и привязать с существующему (т.е. пользователю дается возможность привязать к одному профилю разные аккаунты с разными email. И в принципе кука долгожитель тут не нужна — если пользователь хочет завести новый аккаунт — он это всегда сделает — например из того же in-private режима, с этим бороться бесполезно

4.Что еще стоит собирать и использовать — собственно внутренняя Auth_data — и гугл и fb и все остальные передают свой внутренний id пользователя (формат очень разный =)). его надо помнить\хранить и искать по нему пользователей — т.е. если пришел пользователь с FB, зарегался, потом запретил ваше приложение, пришел повторно и отдал анонимный email — его можно определить по внутреннему FB аккаунту. Та же самая ситуация и с гуглом — если привяжете в один аккаунт несколько адресов (удобно при Google apps for your domain например), то можно не парится и не вспоминать — а какой email я в прошлый раз отдавал — googleId для аккаунта будет один и тот же. Да и все сервисы, кто не отдает email ( твиттер) можно авторизовывать только таким способом. Опять же — креденшиалы без email не могут быть Primary ( для нас).

Ну вот как-то так — кратко непонятно и неподробно ;). Будут вопросы — пишите.
1. Ну, собственно в указанной мной схеме и есть данные, касающиеся пользователя на сайте :) В отличие от auth_data, который нужен для работы с провайдерами. Насчет email немного спорно, имхо. В конце концов, это может быть публичный email, который не жалко показать. Но, в целом, это уже мелочи, поле не сильно на что-то влияет.

Не соглашусь насчет «никакого главного логина». Откуда креденшиал знает, что он главный? И почему профиль об этом не догадывается? Мне кажется более логичной моя структура, хотя и это не сильно критично.

2. А чем Ваша схема отличается от моей? У меня точно также своя сущность (профиль) вынесена в отдельную таблицу (users), а креденшиалы отдельно (в auth_data).

Подтверждения почты? Зачем они нужны при входе через стороннюю службу?

3. Долгожитель нужен для напоминания. Возможность выбрать создание нового аккаунта никто не отменяет :)

4. Да, это нужная вещь. Внутренние IDшники я пока никуда не пристроил, а надо бы. Спасибо, записал в memory.

Разве что не соглашусь с тем, что креденшиалы без мыла не могут стать главными. Хотя бы потому, что может быть ситуация, когда емайл не отдается провайдером, а других привязанных нет. Тут просто становятся невозможными некоторые фичи, завязанные на емайл. Но требовать его от пользователя, я считаю, не стоит. Возможно, у Вас так получается из-за необходимости подтверждать регистрацию по мылу?
1. Мы так и делали сначала, но потом добавили возможность смены email и получили проблемы с обновлениями 2 разных таблиц. Лишнее это

У креденшиала стоит флаг (у нас IsPrimaryEmail). Мы делали по принципу — первый главный, остальные зависимые. Если главный удаляется — следующий становится главным ( по CreateDate)
Главный нам на самом деле нужен только для определения email, куда слать информацию, а так — он не обязательно должен существовать, более того у нас все креденшиалы — равноправны.

2 особо ничем — зависимостей просто меньше и связности — проще рефакторить и понятно как управлять.

подтверждения почты только при регистрации через PlainPassword, в остальных случаях мы естественно доверяем провайдерам.

3.Напоминания чего? что пользователь уже у вас был? Этот долгожитель очень уязвим — ин-приват режим, очистка кукисов, другой браузер, другой компьютер — и все, нету Маклауда…

по поводу креденшиалов без мыла — не вопрос, просто у нас т.к. мыло критично — без мыла нельзя. В остальных случаях — на усмотрение.
1. Понимаете, требовать от креденшиала email несколько неправильно. Если Твиттер/Гитхаб Вам не отдаст мыло, что будете делать? Ну и могут быть варианты, что пользователь не хочет использовать мыло креденшиала для получения информации с сайта (мало ли).

Опять же, если дать пользователю возможность поменять мыло, не в креденшиалс же его записывать!

2. Спорить не буду, может и у нас поменяется.

3. Долгожитель — это всего лишь помощник. Если он потеряется, то ничего страшного не происходит. Определить, существует ли этот пользователь в системе, мы можем еще и по емайлу. И не забываем спросить «может быть у Вас есть аккаунт на нашем сайте?».
1. Хочет ввести руками — можно в PlainPassword запись. И она становится Primary.

Вы поймите что про мыло я говорю только применительно к своей задаче, нам мыло важно — мы его требуем. Если вам не важно — вы с такими провайдерами будете вынуждены работать по их внутренним Id (т.е. по п.4), как иначе вы отличите один твиттер акк от другого если нету мыла и не пользуетесь внутренним ID?
Мыло в данном случае это общий ID — он удобней чем индивидуальные service-specific, но не более…
PS другие провайдеры, которые не отдают мыло — пока просто не подключены, т.к. нету соответствующей инфраструктуры для затребования мыла у пользователя (те. вошел через твиттер — введи почту руками и провалидируй ее. Тут твиттер сам виноват.)
Я так и подумал. Мы в принципе пока что мыло не собираемся требовать. Отсюда и отличия в подходах.
UFO just landed and posted this here
Есть разница — придумать 100 паролей для 100 сайтов, либо помнить парочку для ГМайла/Твиттера, а в остальные заходить через них?
UFO just landed and posted this here
Возможно, как раз потому, что надо придумывать сто паролей ;)
UFO just landed and posted this here
А что всё? Если у меня взломают Гмайл или Твиттер, я меньше всего буду думать о том, что случится с сайтами, на которые я заходил через этот аккаунт. Я ж не интернет-банкинг делаю.

В любом случае, я не прошу пользователя напрягаться лишний раз — в этом главная цель.
Из своего опыта пришёл к тому, что таблицы аутентификации группировать как минимум по типу. Итого в своих проектах у меня:

users
auth_email
auth_openid
auth_twitter
auth_facebook

Считаю этот вариант более удачным и более нормализованным (у вас сущности всё таки разнородные хранятся в одной таблице)
Да, где-то раньше в обсуждениях уже видел Вашу схему. Всегда было интересно, ведь OpenID тоже данные по-разному отдает (насколько помню, Гугл возвращает реальные ФИО, если есть).
А для Github'а и Googl'а тоже отдельные таблички делать? А есть ведь еще и Mail.ru, Яндекс, LinkedIn и т.д.

Чем принципиально будут эти таблицы отличаться? Что есть такого в Твиттере, что надо обязательно сохранить, причем в отдельной таблице? Количество фолловеров, сразу оговорюсь, мне не интересно.

И зачем нужен auth_email?
Если провайдеры отдают разный набор данных — то разделяем

auth_email — для аутентификации по почтовому адресу, соответственно :-) предполагаем, что у нас могут аутентифицироваться как по всяким openid, так и через обычную форму.
> Если провайдеры отдают разный набор данных — то разделяем

Так вот весь вопрос в том, насколько критичны нам эти данные, чтобы мы их разделяли в таблицах. Это ведь получаются уже специфичные для конкретного сервиса данные, нет? Или они действительно у вас используются?
Угумц, согласен, что был слишком категоричен.

Разделяю просто потому, что так кажется «академичнее». Реально никто не мешает у меня везде всё хранить в куче.
А как по мне, так денормализованные таблицы — не есть что-то ужасное. А вообще, NoSQL для таких вещей отлично подходит.
Мне это показалось неудобно, во-первых, тупо напрягает количество однотипных по сути таблиц, во-вторых, считаю это ничем не обусловленной денормализацией (формально да, нормализовано, а вот практически — проще сериализовать «кастомные» поля провайдера, чем предусматривать под каждого таблицу — проще оформить единый для всех провайдеров интерфейс).

Ага. Мне сразу вспомнился пример из жизни — у нас на дипломе парень спроектировал БД для учета оргтехники. И там были отдельно таблицы для принтеров/компов/сканеров и т.д. Его хорошо помариновали вопросами на этот счет, ведь схема получается труднорасширяемая, совсем уж негибкая. Поэтому я сторонник унификации в подобных случаях.
А вот кстати в больших системах типа маркет.яндекс, ебей, амазон вроде как используется такой подход (1 общая таблица и N частных). Об этом можно судить по косвенным признакам: поиск и формы.
Не, ну это ж другой совсем вариант и тут все ок :) Получается, что мы выделяем некоего общего предка (общая таблица) и N детей (частные).

Другой вариант — выделение частностей в таблицу вида аккаунт_ид, ключ, значение, но это уже больше в стиле NoSQL наверное.
Вообще, если на сайте и другая инфа такого же рода, то проще воспользоваться NoSQL, но для одной аутентификации это вероятно будет излишеством, если другие сущности сайта хорошо ложатся на РСУБД.
Нужно сделать авторизацию по отпечаткам пальцев :)
Естественно для этого нужно специальный девайс
Если раньше похищали куки, то теперь — пальцы?
UFO just landed and posted this here
Фанаты «Пилы» дружно усмехнулись
Согласитесь, украсть пальцы намного проблематичней :)
А как быть с телефонами/планшетами? Ткнуть подушечкой пальца в глазок камеры, а потом запустить специальную программу для опознавания? :)
Кстати сами телефоны могут использоваться как самостоятельные средства авторизации, поскольку у них есть такие вещи, как пин-код, сим-карты, договор с оператором сотовой связи.

кстати, у меня есть некоторые мысли по поводу того как это можно реализовать в вебе:
см. ниже…
Уж очень специфично получается. Если есть несколько симок — объединяй. Зашел с компьютера — надо придумывать другой способ войти + опять объединяй аккаунты.

А если я с 3G-планшета захожу, который общий для всей семьи?
>> А если я с 3G-планшета захожу, который общий для всей семьи?

В таком случае, ваш продвинутый сынишка сможет использовать ваши куки, сохраненные пароли, а еще он может на этот планшет установить сниффер и кей-логгер, а еще он может в блокноте отредактировать файл hosts

ну, или, ваша менее продвинутая в этом плане племянница сможет сделать то же самое, заразив ваш планшет трояном, загруженным из вконтакта
На сниффер или кейлогер, а также троян нужны, вроде как, админ. права. Плюс «антивирус»и файервол. На сохранённые пароли — мастер-пароль.
Круто! Значит тот, у кого есть админский пароль от планшета (после описанных выше действий) получает полный контроль над перепиской, а еще и на целой сетью аккаунтов в которых бедные родственники (не имеющие админских прав) имели неосторожность авторизоваться через опен-ид!!!
Странное у Вас представление о семье )))
Моему племяннику 11 лет.
На моем компе седьмая винда
Чтобы поиграть в гонялку/леталку/стрелялку нужны админские права
за неделю племянник умудляется успеть поиграть в 30 (тридцать) разных новых игрушек!
представляете, какой был бы для меня напряг каждый раз отрываться от своих дел (приезжать с работы), чтобы проверить очередную игрульку племянника, инсталлировать ее, удалить все предыдущие, в которые он уже поиграл…

мне гораздо прощее поставить рядышком для себя любимого еще одну такую же винду (на втором разделе) и выбирать нужную при загрузке
Вы не поверите, но у кого админский пароль, тот имеет доступ ко всему на компьютере!
Современные сканнеры настолько слабы что сканнеры отпечатков в ноутах — больше дыра в безопасности чем защита. Отпечаток распечатывается на бумаге, а в некоторых случаях можно и по «мусору» аутентифицироваться. Соответствующие статьи легко гуглятся.
Прочтя заголовок, я ожидал нечто большее:

На многие сайты, требующие авторизации я захожу с мобильного телефона,
при этом использую браузер Опера-Мини:

> Кликнули по кнопке «войти через», ввели свой OpenID
> или просто нажали на картинку провайдера.
> Подтвердили/доказали провайдеру, что Вы — это Вы.

такой способ там точно не прокатит!

Зато можно проделать такой финт:

Нажать ссылку «Войти через телефон».

<a href="tel:88003330890">8-800-333-0890</a>

при нажатии на ссылку телефон пытается дозвониться по указанному номеру
дождавшись одного длинного гудка пользователь вешает трубку
(либо после третьего гудка модем на стороне сервера сам сервера вешает трубку)

после этого пользователь нажимает кнопку «Войти», (либо на кнопку «Другой номер» если номер сервера был занят).

в ответ сервер просит ввести последние 2 или 4 цифры своего телефона (в зависимости от числа звонков, поступивших в последние 30-40 секунд)

если все в порядке — входим в закрытую часть сайта
если останутся какие-то сомнения, то сервер может попросить ввести еще например три цифры (в начале номера).
Хм, пошли совсем уже интересные вещи ))

1. Почему не прокатит? Вы же по ссылкам как-то щелкаете?
2. А что это было с телефоном? :) О чем мне скажет Ваш номер сотового?
>> Почему не прокатит? Вы же по ссылкам как-то щелкаете?

Не прокатит хотя бы потому, что в опере-мини (по крайней мере в версии java2me) нет никакой возможности просмотреть адрес гиперссылки по которой вас направят с сайта.
То есть, вас запросто могут направить на фишинговый сайт, очень похожий по внешнему виду на страницу авторизации вашего любимого опен-ид провайдера, и стыбрить пароль для вашего аккаунта (читай от целой кучи аккаунтов в смежных сетях, на которых вы регистрировались по опен-ид).
Авторизуйтесь на своем любом провайдере заранее, чтобы оставалось только подтвердить разрешение.
Тоже не вариант: постоянно держать открытым сессию в основном провайдере (причем на мобильном телефоне!), в надежде что в ближайшее время нужно будет войти (и не просто войти но и залогиниться по опен-ид) на какой-то левый сайт — слишком уж напряжно.
Примерно понял, о чем Вы. Есть ведь более простые схемы — указываем номер телефона на сайте, в ответ приходит СМСка с кодом подтверждения (4-6 цифр или букаф).
Подтверждение через СМС — хуже не придумаешь!
Потенциальный злоумышленник может иметь
длинный список телефонов своих врагов
и не менее длинный список таких подобных сервисов
по котороым сервисы из второго списка будут регулярно в 3 часа ночи
отправлять сообщения жертвам из первого списка.

Если же злоумышленник просто мелкий хулиган,
то список номер один он может сгенерировать рандомно.
Но ведь согласитесь, что специально обрабатывать телефонные звонки — это как-то чересчур для авторизации на обычном сайте?
Уж, поверьте мне — это гораздо проще habrahabr.ru/qa/7323/, чем использовать тот же самый опен-ид консумер на своем сайте.
А что сложного в ОпенИд-то? ))
То, что на хостинге опен-ид консумера должны быть разрешены исходящие соединения.
Поставить модем на такой хостинг проще? :)
Вводим номер телефона и ждём его соответствия на АОНе сервера-авторизатора…
По-моему это годится только для сайтов с высокими требованиями к безопасности и только при добровольном выборе такого способа пользователем. Например, пассворд менеджер у меня куда более секурен, чем телефон — прочитать смску на моём телефоне имеют возможность куда большее число знакомых мне людей, чем взломать менеджер, подобрать мастер-пароль или установить кейлоггер или сниффер.
Это небезопасно, скажете Вы, и вероятно будете правы. Поэтому при генерации токена сохраняем также различную информацию о клиенте (IP, User-Agent и т.д. — выбор есть).

В подавляющем большинстве случаев для «расшаренных» компов это информация будет совпадать — мы не можем определить человека, который сидит за компом. Потому, как минимум, нужно предусмотреть поле неявное «чужой компьютер» или явное «запомнить меня», а ещё лучше через этот токен хранить провайдера и ид у него и проводить повторную аутентификацию. Если пользователь залогинен у провайдера, то она пройдёт прозрачно (иногда не совсем, но не сложно в любом случае) для него, если нет — залогинится может с тем же ид, может с другим. Если с другим, то старый токен удаляем и генерим новый, если с тем же — обновляем старый (а можно и не обновлять).

Необходимость примари аккаунта со стороны пользователя не понял.
Про галочки я уже писал. Насчет автонаправления на логин — вероятно, так и сделаем.

Необходимость его относительная. К примеру, при привязке аккаунтов к существующему профилю можно использовать вход чере примари как подтверждение. На данный момент мы считаем это удобным, убрать несложно.
Я вообще тему не понял: какой смысл обсуждать какие-то таблицы, когда не продумана логика.
Таблицы нужны только как фундамент, чтобы описать базовые элементы. Соответственно и обсуждаем мы в основном алгоритмы, а не сами таблицы.

PS. У Вас есть предложения по логике?
Для авторизации через соцсети использую Loginza API
Рад за Вас :)

В чем профит? (ведь на самом деле реализовать авторизацию через OpenID/OAuth несложно, мы это знаем) Как избегаете дублированных аккаунтов и тд?
Sign up to leave a comment.

Articles