Как найти страницу авторизации на сайте

Студворк — интернет-сервис помощи студентам

Добрый день! Мой вопрос может не имеет отношения к PHP, я не знаю, в каком именно форуме задать вопрос.
Скажите пожалуйста, как узнать строку авторизации на сайте? Я использую IE, в нем есть F12. Можно ли в F12 посмотреть строку авторизации?
Например на этом форуме можно авторизоваться: ввести логин и пароль. Как можно узнать, какая строка авторизации на этом форуме?
Я хочу авторизваться с помощью программирования (не веб-программирования).
Я себе представляю так структуру строки авторизации:
http://сайт/страница?login=»логин»&password=»пароль»

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

Способы создания авторизации на сайте. Руководство с примерами. Безопасность в браузере

Уровень сложности
Средний

Время на прочтение
14 мин

Количество просмотров 5.7K

В данной статье мы разберем 4 способа как зарегистрировать нового пользователя:

  1. Сторонние сервисы авторизации (такие как Google)

  2. Авторизация с использованием токенов

  3. Авторизация с помощью номера телефона

  4. Логин + Пароль

Статья даст вам конкретный алгоритм реализации каждого способа. Необходимые библиотеки, а также примеры кода. Я постараюсь приводить в пример реализацию на чистейшем JavaScript, для того чтобы вы смогли внедрить функционал в свое проект, не зависимо от используемого фреймворка, однако также будут примеры для тандема Angular + Asp .Net Core. Мы обсудим как защитить ваш сайт от взлома. На сколько это сложно и возможно ли в принципе гарантировать 100% защиту. Итак, давайте приступим.

Регистрация. Аутентификация. Авторизация.

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

Начнем с процесса регистрации. Перед вами форма с несколькими полями: Имя, Логин, Пароль, Кличка вашей собаки и т.д. Вы покорно заполняете все поля со звездочками, после чего жмякаете на кнопку “Зарегистрироваться”. Ваши данные отправляются на сервер при помощи HTTP, сервер создает в базе данных новую запись, и если все проходит успешно, то вы зарегистрировались в системе. То есть процесс регистрации – это просто сохранение на сервере “в определенном текстовом файле” данных, которые вы заполнили на сайте.

Это пример самого простого способа регистрации, который только можно представить. В реальности так никогда не делают, но вот общий принцип неизменен. Более подробно, как происходит процесс регистрации в современных системах, мы разберем позднее, а сейчас давайте взглянем на процесс авторизации.

Когда вы заходите в свой аккаунт в социальной сети, то у вас отображаются только ваши фотографии, видео и посты. Тоже самое происходит, для любого другого человека и это не кажется странным. Но все данные, о том сколько у вас картинок, историю сообщений и даже рекомендации, которые заточены именно под вас, нужно где-то хранить. Хранить их нужно очевидно на сервере, т.к если сохранить эти данные в браузере, то они будут доступны вам, только с одного устройства (где вы регистрировались). Как уже было сказано, при регистрации, для каждого пользователя создается “файл” на жестком диске сервера, в котором будут храниться все данные. В момент авторизации, данные, введенного вами логина и пароля отправляются на сервер, где среди всех файлов, относящихся разным людям по логину ищется именно ваш, после чего проверяется соответствует ли отправленный пароль, тому который сохранен в файле и если да, то в браузер возвращаются необходимые данные пользователя. То есть процесс авторизации – это получение с сервера нужных данных о пользователе.

Разница между аутентификацией, идентификацией и авторизацией

По большому счету – это разные этапы одного процесса (предоставление доступа пользователю).

И хоть все эти этапы и разделяют, но обычно в процессе реализации – это могут быть просто 3 разных метода (функции), вызывающихся в приложении последовательно.

Разделение также нужно для тех случаев, если вы можете опустить какой-либо из этапов (и выполнить только 2 других). К примеру, пользователь прошел все 3 этапа и получил токен доступа. Токен подтверждает тот факт, что человек прошел аутентификацию, а значит при следующем обращении можно опустить этот этап. Backend приложение должно будет только проверить id пользователя (хранящийся в токене) и по id достать права.

Далее под словом “авторизация” (для простоты) будет подразумеваться весь процесс получение доступа.

Что представляет из себя база данных.

Выше я писал про чудесный “текстовый файл”, в котором хранятся все данные пользователей. Вы безусловно можете организовать хранение данных в обычных .txt файлах, но на практике так никто не делает. Данная формулировка была использована, для того чтобы вы понимали, что ваши данные хранятся на жестком диске, таким же образом, как вы храните у себя на компьютере фотки, записи и видео.

Но используют для этих целей определенные программы “Базы данных”. База данных – это программа, которая работает в фоновом режиме, функциями которой вы можете пользоваться из других программ (написанных вами). Что это за функции? – если коротко, то это операции сохранения и получения данных, но в отличии от обычного текстового файла, база данных выполняет операции сохранения и получение намного быстрее (Особенно когда этих данных становится очень много).

Таким образом работу backend приложения можно представить, как работу 2-х независимых программ:

  1. Серверное приложение – программа, которая отвечает за функционал сервера

  2. База данных – программа, которая отвечает за управление данными, и которую использует серверное приложение. При этом База данных не может использовать функционал серверного приложения.

Почему современные приложения не используют логин + пароль для авторизации.

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

Основной момент – обеспечение безопасности. Давайте взглянем на основные методы, с помощью которых злоумышленники могут получить доступ к вашему аккаунту:

  • Фишинг – хакеры могут создать копию сайта, на котором вы введете свой логин и пароль. После чего эти данные сохраняются на сервере злоумышленников, и они могут войти в ваш аккаунт используя их. Сюда же входят различные звонки от сотрудников банка, которые просят предоставить информацию.

  • Перебор паролей автоматическим программами.

  • Перехват трафика – для того чтобы залогиниться на сайте нужно отправить на сервер логин и пароль с помощью HTTP , которые могут быть перехвачены хакерами.

  • XSS – вставка на сайт вредоносного JS кода, который будет изменять логику приложения.

Какой бы метод авторизации вы не использовали он не спасет от взлома, если будут использованы фишинг или перебор паролей. Просто потому что в первом случае вы “по собственной воле” говорите свой пароль, а во втором этот пароль у вас “отгадывают”. Но в любом случае хакеры узнают ваши данные для входа в том виде, в котором используете их вы. А значит для приложения теперь вы ничем не отличаетесь (Ну разве что IP с которого будет происходить вход). Здесь единственная мера защиты – это смотреть на каком сайте вы вводите пароль и использовать сложный пароль. “Усовершенствованные” методы авторизации спасают именно в тех случаях, когда злоумышленники пытаются косвенно получить ваши данные (к примеру перехватом трафика).

В чем проблема авторизации при помощи логина + пароль

Для получения любых данных вашего пользователя нужно доказать серверу, что вы – это вы (введя пароль и отправив его на сервер). Таким образом, в такой модели авторизации web-приложение будет каждый раз обмениваться логином и паролем с сервером при необходимости, а это опасность перехвата. В дополнении к этому логин и пароль придется где-то хранить (Чтобы использовать их в последующих запросах к серверу. Иначе придется постоянно просить пользователя ввести пароль при переходе на новую страницу) – следовательно есть возможность получения доступа к этим данным в случае использования XSS.

Чтобы избежать данных проблем в процессе авторизации используют специальные ключи – токены, которые с одной стороны не содержат приватных данных (паролей), а с другой помогают серверу идентифицировать пользователя.

Использование токенов в процессе авторизации

Токен представляет из себя простую строку из символов, на примере этой:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYX
QiOjE2Nzc5MTcxOTYsImV4cCI6MTcwOTQ1MzE5NiwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViI
joianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2Nr
ZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN
0IEFkbWluaXN0cmF0b3IiXX0.sBi4RpRuoIHRisficYOs3278nuu83ufS9ZUH-IkDGRs

Давайте кратко опишем этапы авторизации с помощью токена:

  1. Ввод логина и пароля.

  2. Шифрование (преобразование логина и пароля в закодированную строку).

  3. Передача шифрованных данных на сервер.

  4. Генерация сервером токена доступа, с помощью которого web-приложение будет обращаться к backend приложению для получения данных.

  5. Отправка токена обратно в браузер.

  6. Сохранение токена в локальном хранилище или в куки, для дальнейшего использования.

Суть здесь в том, что мы 1 раз передаем приватные данные по сети, после чего используем токен, который содержит только публичные данные.

Прежде чем погружаться в детали каждого этапа, давайте взглянем на то, какие типы авторизации с использованием токенов существуют. Все типы можно разделить на 2 группы, которые различаются способом генерации токена доступа:

Авторизация на самом сайте

В этом случае логин и пароль, вводятся на том сайте на котором вы сейчас находитесь, после чего они кодируются и отправляются на сервер, где генерируется токен и возвращается на сайт.

Авторизация на стороннем сервисе (Gmail)

Здесь пользователя перебрасывает на сторонний ресурс (открывается новая вкладка или окно браузера), где он вводит данные авторизации. Этот метод, отличается тем, что во-первых – это намного проще для пользователя. А во-вторых – не нужно вводить данные от вашего аккаунта (к примеру от аккаунта Google), на неизвестном сайте, который запрашивает регистрацию. Пользователь вводит свои данные, сторонний сервис (в нашем случае Gmail) генерирует токен доступа и отправляет его на тот сайт, с которого перешел пользователь. После чего сайт работает уже не с вашими авторизационными данными от сервиса, а с токеном.

Этапы такой авторизации описываются в стандартах – OAuth и OAuth 2.0. Обе версии описывают один и тот же алгоритм, но 2 версия – более защищенная.

Этапы такой авторизации описываются в стандартах – OAuth и OAuth 2.0. Обе версии описывают один и тот же алгоритм, но 2 версия – более защищенная.

Алгоритм авторизации – подробно.

  1. После того как пользователь ввел свои данные, то желательно их закодировать, чтобы не передавать по сети в простом текстовом виде. Здесь можно использовать любой алгоритм шифрования, можно даже закодировать в простую Base64 строку. Дело в том, что из браузера не получится зашифровать данные так, чтобы гарантировать их 100% безопасность при передаче по сети, т.к для этого нужно использовать какой-то ключ, который знает и сервер и браузер (чтобы первый смог закодировать, а второй декодировать). Но поскольку любые данные в браузере – публичные и при желании код в браузере можно посмотреть, то и этот ключ хакеры могут потенциально перехватить. Таким образом мы хоть и кодируем данные при передаче из браузера, но при желании и должных знаниях эту информацию можно узнать. Поэтому момент передачи логина и пароля связан с определенными рисками.

  2. Итак, авторизационные данные пришли на сервер. Бекенд приложение декодирует полученные данные и добавляет новую запись с вашими данными в БД (базу данных). После чего в ответ возвращается строка(токен). Особенность этой строки в том, что она закодирована при помощи уникального ключа, который известен, только бекенд приложению. Внутри этой строки закодированы какие-то данные и никто, кроме сервера (даже клиентское приложение), не может узнать что-это за данные (для этого нужен ключ).

  3. Токен возвращается на клиент и если в дальнейшем браузер захочет запросить данные, то он вместе с http запросом должен будет отправить токен, который будет декодирован на сервере, чтобы убедиться что вы это вы. И что токен не был изменен в процессе (если его изменить, то сервер не сможет декодировать его, что будет сигнализировать о потенциальной попытке взлома).

  4. Токен может передаваться любым способом. Вы можете поместить его в тело (Body) http запроса, передать через куки или в Header. Здесь цель просто доставить эту строку на сервер. При этом обычно токен отправляется как дополнительный заголовок хедера:

Для передачи токена используют хедер, потому что – это во-первых, удобнее, т.к вам не нужно модифицировать структуру каждого вашего запроса и помещать его в Body. А во-вторых, многие библиотеки, реализующие авторизацию, работают именно с хедером запроса.

JWT(JSON Web Token)

Как мы выяснили любой токен представляет из себя строку. И каждое приложение, которое реализует процесс авторизации, может на свое усмотрение использовать любую структуру токена. Но для браузерной авторизации чаще всего используют JWT токен. Это просто некоторый общепринятый стандарт.

Что представляет из себя этот стандарт ? Как можно догадаться из названия, этот стандарт основан на JSON и позволяет передавать вместе с токеном любой JSON объект (а поскольку мы можем любые данные представить в качестве объекта, который в последствии будет превращен в JSON, то внутри JWT можно передавать всё что угодно). JWT состоит из 3-х частей:

1) Header

2) Payload

3) Уникальный ключ, для шифрования

Получается у нас есть объект, состоящий из 3-х полей. В хедере мы указываем, что за тип токена мы используем и как будут кодироваться данные. В секции payload – данные, которые мы хотим передавать с сервера на клиент и обратно. А уникальный ключ – это пароль, с помощью которого мы кодируем 2 предыдущих части и превращаем их в строку.

Ключ, всегда хранится только на сервере. И клиентское приложение не имеет к нему доступа. Таким образом гарантируется, что изменить токен может только приложение у которого есть этот ключ (то есть только сервер). Здесь важно, что именно ИЗМЕНИТЬ, т.к декодировать токен и получить из него header и payload может любой, кто получил этот токен. Эти данные публичные.

Алгоритм генерации JWT токена на Java Script

Алгоритм генерации JWT токена на Java Script

Сначала мы превращаем header и payload в base64. Далее используем алгоритм шифрования из библиотеки Crypto Js, для того чтобы закодировать две полученные base64 строки и получить сигнатуру(которая тоже является строкой). После чего просто объединяем 3 полученные строки в одну, разделяя точками.

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

Access и Refresh токены

На данном этапе мы выяснили, что такое JWT, какую структуру он имеет, а также как происходит валидация токена. Хакеры не могут изменить данные нашего токена (и вставить к примеру свои). Но перехватить токен и использовать его для доступа к аккаунту, могут. Ведь токен содержит все нужные данные для авторизации и любой человек получивший к нему доступ, не будет отличаться для сервера от настоящего владельца аккаунта.

Для решения этой проблемы существуют Access и Refresh токены. Здесь мы не начинаем использовать какой-то новый способ авторизации. Используется все тот же JWT, но теперь единственный токен, который у нас был мы называем Access Token, при этом в дополнении к нему появляется второй Refresh токен, который также представляет из себя строку, имеет одинаковую структуру с Access Token, поэтому может хранить внутри какие-то данные (хоть и не обязательно и обычно это не требуется).

Важно то, что у Access и Refresh токенов появляются обязательные поля внутри их payload (iat, exp). Об их существовании я уже упоминал, но когда у нас есть только 1 токен, то эти поля по большому счету не используются и содержат дополнительную информацию.

Iat (issued at time) – время, когда токен сгенерирован.

Exp (expiration time) – время, до которого токен будет считаться валидным.

Алгоритм авторизации с использованием Refresh и Access токенов.

  1. Пользователь вводит логин и пароль. Они отправляются на сервер (Аналогично с использованием одного токена).

  2. Сервер создает/находит пользователя в Базе данных, после чего генерирует 2 токена (генерация происходит по уже известному алгоритму), но в этот раз добавляются iat и exp поля. При этом для Access Token, exp – устанавливается на короткий срок (15 -20 минут), а вот для Refresh Token, значение exp задается большим (несколько дней или недель).

  3. Далее сервер возвращает 2 токена в браузер, где они сохраняются в локальном хранилище.

  4. Теперь, если клиентское приложение хочет получить доступ к данным, то прежде чем отправлять запрос с Access Token в заголовке, нужно проверить не истек ли его срок жизни и если, нет, то отправлять запрос, если же токен expired, то прежде чем отправлять запрос нужно обновить токен (а иначе сервер получит не валидный токен и вернет ошибку).

  5. Для того чтобы обновить Access Token, клиент отправляет специальный запрос, в котором отправляет Refresh Token. Сервер, получает этот Refresh Token и на его основе генерирует новую пару Access + Refresh токенов, которые возвращаются на клиент и опять сохраняются. Однако в случае, если при создании новой пары токенов, оказывается, что и Refresh Token уже устарел, то возвращается ошибка и пользователя просят еще раз ввести свой логин и пароль.

Почему нельзя обойтись одним Access токеном

Как мы ранее выяснили 1 токен защищает от ситуаций, когда хакеры меняют данные внутри токена (payload), но не защищают от того, что с похищенным токеном злоумышленник может получить доступ к аккаунту пользователя. Refresh Token частично решает эту проблему.

Давайте разберемся что у нас произойдет, если ваши токены похищены. Хакер получил доступ к вашему аккаунту и может делать все что угодно, до тех пор пока вы не зайдете в систему. Потому что в этот момент истечет срок действия вашего Access токена и вам придется обновить пару токенов на новую, следовательно похищенные токены станут не валидными. Или представим др. ситуацию. Хакер провел долгое время на вашей странице, а значит требуется обновить Access Token с его стороны (что он успешно сделает), ведь он завладел обеими (в том числе и Refresh). Следовательно, теперь уже когда вы попытаетесь зайти в свой аккаунт сервер вернет ошибку, т.к уже ваш Refresh Token не валидный, после чего вы введете свои данные и не валидной станет пара токенов, похищенная злоумышленником.

Таким образом, Access и Refresh токены не защищают полностью от взлома, но сильно усложняют жизнь взломщикам (т.к похищенный токен нельзя долго использовать).

Где хранить токены

Есть 2 популярных варианта Local Storage и куки (либо внутри сессионного хранилища). И хранить пару Access и Refresh токенов лучше в куки. Это обосновано тем, что если на сайт встроят вредоносный код, то через JS хакеры могут получить доступ к Local Storage, но вот куки не хранятся в локальном хранилище браузера, они передаются с запросом. Соответственно, для того чтобы получить к ним доступ, нужно сделать как минимум один запрос авторизации. (с неизвестными логином и паролем).

Хотя существуют методики и для хищения данных из куки. Здесь нужно запомнить один момент. У вас не получится на 100% защититься от всех атак в браузере, но чем больше уровней защиты вы установите, тем меньше вероятность взлома.

Авторизация через внешние сервисы

Общий алгоритм добавления авторизации через сторонние сервисы следующий:

  1. Вам нужно сделать редирект со своего сайта на сайт сервиса.

  2. Дождаться пока пользователь введет там свои данные и сервис сгенерирует токен авторизации.

  3. Дождаться HTTP respons-а от стороннего сервиса и получить токен доступа (внутри которого хранятся данные о пользователе).

  4. Отправить полученный токен уже на собственный сервер и сгенерировать пару Access + Refresh токен на основе данных пользователя. После чего сохранить их в браузере.

  5. А далее идет обычный flow с JWT авторизацией, описанный выше.

А теперь на примере Gmail авторизации давайте взглянем на детали:

В Gmail, ровно как и в других похожих сервисах первое что вам нужно будет сделать – это создать “Приложение” для вашего сайта на специальном сервисе для разработчиков. У каждого сервиса авторизации он свой. Для Google – это Developer Console.

Как вы могли догадаться целью создания профиля является получение этого самого ключа. У гугл он называется Client Id. Client Id будет использоваться в нашем frontend приложении. Вот как это может выглядеть на TypeScript:

HTML

<button>Sign In with Google</button>

Type Script

DIALOG_PARAMS – настройки окна, где пользователь будет вводить авторизационные данные.

googleAuthListener – слушает сообщения от GMail и в случае успешной авторизации возвращает ответ с кодом авторизации (это не тоже самое что токен, но с его помощью можно получить токен).

dialogUrl – URL на который переходит пользователь для ввода логина и пароля.

Авторизация по номеру телефона

Авторизация по номеру телефона почти идентична обычной с использованием логина и пароля с той лишь разницей, что теперь вместо email мы используем номер, а вместо пароля, одноразовый проверочный код. На этом моменте не нужно долго останавливаться.

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

Сервисы для отправки Email и СМС сообщений.

Начнем с отправки email. Чтобы отправить сообщение на почту вам необходим SMTP сервер (и без него обойтись не получится). Здесь есть 2 варианта:

Вариант 1 – сложный. Вы создаете отдельный свой сервер и настраиваете его, чтобы он понимал SMTP протокол. В большинстве случаев это слишком сложно и излишне.

Вариант 2 – рациональный. Вы используете сторонние сервисы, которые берут на себя работу по обслуживанию SMTP сервера, а вам предоставляют, либо готовый API для отправки сообщений, либо сам адрес SMTP сервера, который вы можете использовать.

Как вы могли догадаться, в обоих случаях удовольствие это не бесплатное. Или почти не бесплатное. В случае с SMTP сервисами, многие провайдеры предоставляют триал или бесплатное использование на время разработки (то есть у вас все будет работать, но только на маленьких нагрузках). Одним из таких сервисов является SMTP.bz.

Для того чтобы отправить email с помощью этого сервиса, нужно зарегистрироваться и привязать домен вашего сайта (на сервисе есть инструкция), после чего вам выдаются логин, пароль, адрес и порт от сервера, которые нужны для подключения к SMTP. Приведу небольшой кусок кода (на C#), как отправить Email используя SMTP сервер.

Теперь разберемся с сервисами для отправки СМС сообщений. В этом случае у нас также есть готовые API для отправки смс. Например — smsc.ru. Использование довольно простое – отправка http запроса с номером телефона и сообщением.

Однако в данном случае я не нашел сервисов, у которых есть бесплатные периоды (Напишите в комментариях если вы знаете такие) Возможно это связано с тем, что в цепочке отправки смс также участвует сотовый оператор, который взымает плату за отправку с “смс сервисов”. Потому они не могут предоставить бесплатный триал доступ, как в случае с SMTP.

А нужна ли вам вообще авторизация на сайте ?

Любая авторизация – это очень очень сложно для пользователя. Поэтому по возможности не надо донимать регистрацией. Если у вас лендинг, блог или информационный сайт, который не подразумевает личного кабинета и уровней доступа, то вообще не делайте авторизацию. Потому что а зачем она вам ?

Заканчиваем

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

Система авторизации с помощью cookie на PHP

loader

В прошлом уроке мы изучили механизм взаимодействия с cookie в языке PHP.

Теперь давайте попробуем применить эти знания на практике — создадим простейшую систему авторизации с использованием этих самых cookie. Ведь для авторизации нам просто необходимо при каждом запросе идентифицировать пользователя — сохранив специальное значение в куки этого легко добиться!

Техническое задание

Начнём мы это дело с описания будущей системы. Пусть у нас будут следующие компоненты:

  1. Главная страница сайта с каким-либо содержимым. Вверху страницы выводится:
    • если пользователь авторизован: Добро пожаловать, %username%.
    • если пользователь неавторизован: Авторизация — слово является ссылкой, которая ведёт на форму авторизации.
      Авторизован пользователь или нет, определяется с помощью cookie.
  2. Страница с формой авторизации. Два инпута для логина и пароля и кнопкой «Вход». Если введены правильные логин и пароль, устанавливаются cookie со значениями переданных данных, а затем пользователя автоматически редиректит (перенаправляет) на главную страницу.
  3. Страница для разлогинивания — при переходе на неё cookie будут удаляться из браузера пользователя, а затем выполняется редирект на главную страницу.

Решение

Продумываем архитектуру

Первое, о чём нам нужно подумать — это то, как будут храниться элементы этой системы, и сколько их вообще будет.

Начнем с простого — для начала у нас должно получиться 3 странички, которые мы описали в ТЗ.

Ещё нам потребуется функционал, который будет проверять, авторизован ли пользователь. Если мы перечитаем ТЗ, то поймём, что он используется в двух местах — и на главной странице и на странице авторизации. Значит, стоит вынести этот механизм в отдельный файл, и использовать его в двух местах сразу.

Ну и наконец, нам где-то нужно хранить самих пользователей, а именно — их логины и пароли. Создадим для этого простенькую «базу данных» — массив, с набором пар логин-пароль. Это ещё один файл.

Пишем код

Все исходники по данному заданию доступны здесь.

База данных

Ну вот, всё продумали, осталось только написать. Предлагаю начать с нашей базы данных. Создадим файл usersDB.php и запишем в него несколько пользователей.

<?php
return [
    ['login' => 'admin', 'password' => '[email protected]'],
    ['login' => 'moderator', 'password' => 'password'],
    ['login' => 'user', 'password' => '123'],
];

Функции проверки авторизации

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

<?php
function checkAuth(string $login, string $password): bool 
{
    $users = require __DIR__ . '/usersDB.php';

    foreach ($users as $user) {
        if ($user['login'] === $login 
            && $user['password'] === $password
        ) {
            return true;
        }
    }

    return false;
}

В цикле мы пробегаемся по базе данных пользователей и пытаемся найти пользователя с переданными логином и паролем. Если такой пользователь в массиве найден — возвращаем true. Иначе — false.

Давайте теперь ещё напишем функцию, которая будет возвращать логин текущего пользователя. Эта функция будет проверять текущие значения cookie с ключами login и password с помощью уже существующей функции checkAuth. При этом если пользователь найдётся, то она вернёт его login, а иначе — null. Назовём эту нашу новую функцию getUserLogin.

//продолжение файла auth.php

function getUserLogin(): ?string
{
    $loginFromCookie = $_COOKIE['login'] ?? '';
    $passwordFromCookie = $_COOKIE['password'] ?? '';

    if (checkAuth($loginFromCookie, $passwordFromCookie)) {
        return $loginFromCookie;
    }

    return null;
}

На этом всю логику проверки логина мы описали. Теперь займёмся непосредственно страничками.

Главная страница

Создадим файл index.php. Для простоты примера мы будем использовать только строку с приветствием авторизованного пользователя, либо ссылкой на авторизацию. В этой странице нам потребуется функция проверки авторизации через cookie, поэтому здесь нужно подключить файл auth.php.

<?php
require __DIR__ . '/auth.php';
$login = getUserLogin();
?>
<html>
<head>
    <title>Главная страница</title>
</head>
<body>
<?php if ($login === null): ?>
<a href="/login.php">Авторизуйтесь</a>
<?php else: ?>
Добро пожаловать, <?= $login ?>
<br>
<a href="/logout.php">Выйти</a>
<?php endif; ?>
</body>
</html>

Наша главная страничка готова. Можно зайти на неё и убедиться, что мы не авторизованы.

Главная страничка с призывом авторизации

Форма авторизации

Давайте теперь сделаем форму авторизации — создаём файл login.php и для начала набрасываем саму HTML-форму. Шаблон получился следующим.

<html>
<head>
    <title>Форма авторизации</title>
</head>
<body>
<form action="/login.php" method="post">
    <label for="login">Имя пользователя: </label><input type="text" name="login" id="login">
    <br>
    <label for="password">Пароль: </label><input type="password" name="password" id="password">
    <br>
    <input type="submit" value="Войти">
</form>
</body>
</html>

Давайте теперь добавим логику проверки переданных данных.

<?php
if (!empty($_POST)) {
    require __DIR__ . '/auth.php';

    $login = $_POST['login'] ?? '';
    $password = $_POST['password'] ?? '';

    if (checkAuth($login, $password)) {
        setcookie('login', $login, 0, '/');
        setcookie('password', $password, 0, '/');
        header('Location: /index.php');
    } else {
        $error = 'Ошибка авторизации';
    }
}
?>
<html>
<head>
    <title>Форма авторизации</title>
</head>
<body>
<?php if (isset($error)): ?>
<span style="color: red;">
    <?= $error ?>
</span>
<?php endif; ?>
<form action="/login.php" method="post">
    <label for="login">Имя пользователя: </label><input type="text" name="login" id="login">
    <br>
    <label for="password">Пароль: </label><input type="password" name="password" id="password">
    <br>
    <input type="submit" value="Войти">
</form>
</body>
</html>

Логика простейшая — если был отправлен POST-запрос, проверяем правильные ли логин и пароль были переданы.

Если нет — то создаём переменную $error, в которой пишем об ошибке авторизации. Позже в шаблоне выводим эту ошибку, если эта переменная объявлена.

Если же авторизация прошла успешно, мы устанавливаем cookie с ключами login и password, в которые помещаем значения из POST-запроса. После этого выполняем редирект на главную страницу.

Редирект делается с помощью заголовка в HTTP-ответе. Этот заголовок называется Location и выглядит следующим образом:

Location: адрес_на_который_нужно_перейти

Для формирования заголовков в PHP используется функция header – ознакомиться с ней более детально вы можете здесь.

Теперь можно попробовать нашу страничку в действии. Давайте для начала введём несуществующую пару логина и пароля. Например, 123:123.

Ошибка при авторизации

Мы увидим соответствующую ошибку.

Теперь давайте зайдем под пользователем user. В нашей БД для него указан пароль 123. Пробуем…

Успешная авторизация

Успех! Нас автоматически перекинуло на главную страницу, где мы видим приветствие для данного пользователя!

Безопасная система авторизации

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

Хеширование паролей

В более совершенных системах авторизации используют хеш от пароля.

Если по-простому, то это такое вычисленное значение, полученное в результате выполнения над паролем определенных манипуляций. В результате этих действий мы получаем строку, из которой нельзя восстановить исходный пароль.

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

Для чего это делается? Да просто потому, что если сайт будет каким-то образом взломан, то злоумышленник в базе данных не найдёт паролей в открытом виде — только хеши. А так как из хеша получить пароль довольно сложно (при условии, что хеш-функция надежна и используется надёжный пароль), то пароль он не узнает. Следовательно:

  1. злоумышленник не сможет использовать пароль для входа на взломанный сайт;
  2. он также не сможет использовать этот пароль для входа под тем же логином и паролем в другие места (ведь довольно часто люди используют одинаковые пароли для всего).

Вычисляются хеши с помощью хеш-функции. Хеш-функции при этом вычисляют хеши следуя алгоритмам хеширования. Сейчас в PHP для хеширования следует использовать функцию password_hash(), а для проверки хеша — password_verify(). Если вы в каком-то уроке увидите, что для хеширования паролей используется md5 — бегите оттуда, такие хеши вскрываются за несколько минут, она устарела ещё лет 10 назад.

Авторизационные токены

Помимо хеша пароля в базе данных так же принято хранить так называемые авторизационные токены (AuthToken). Это комбинация символов (желательно подлиннее и с кучей кракозябр), которая генерируется при успешной авторизации пользователя и сохраняется в базе данных. А ещё она и пользователю отправляется.

И потом пользователь с помощью cookie передает этот токен на сервер, где он сравнивается со значением в базе данных. Если они равны, то считаем пользователя авторизованным. Для чего? Дело в том, что куки могут быть похищены злоумышленниками (очень многими способами, не будем об этом в этой статье, кому интересно — погуглите). И если злоумышленнику попадет в руки токен — он не сможет получить исходный пароль. О том, почему это так важно, я уже объяснил.

Заключение

Повторюсь, два последних параграфа здесь только для ознакомления. Реализуем мы их в дальнейших уроках, когда будем знать чуть больше вещей. Пока что — вот такая простейшая, но небезопасная система авторизации.

Ах да, чуть не забыл, все исходники к каждому уроку я для вашего удобства буду выкладывать на github – вот тут.

loader

loader

Совет, как можно быстро подключиться к незакрытой публичной Wi-Fi-сети. 

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

Большинство из этих общедоступных сетей Wi-Fi требуют, чтобы пользователи авторизовались с помощью мобильного телефона или электронной почты, соглашаясь с ограничениями использования доступа в Интернет, а также подтверждали свою личность. Часто это утомительный процесс. Но еще хуже, когда эти страницы входа в систему не отображаются автоматически. В итоге, подключившись к какой-нибудь сети, вы не сможете выйти в Интернет, пока не авторизуетесь. Но как быть, если автоматически не появляется форма/страница авторизации публичной Сети?

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

Перезагрузите ваше устройство или сбросьте настройки Wi-Fi

Первое и самое простое – это перезагрузить ваше устройство. Если вы не хотите делать полный перезапуск, вам может помочь простое включение и выключение Wi-Fi на вашем устройстве. После того как вы полностью перезапустили смартфон или планшет (или включили и выключили Wi-Fi), попробуйте снова подключиться к беспроводной сети и открыть какой-нибудь веб-сайт, чтобы начать процесс входа в систему.

Перенаправить телефон на страницу входа публичной сети

Если это не сработает, попробуйте следующий шаг: попытайтесь принудительно загрузить страницу входа, установленную по умолчанию в маршрутизаторе (роутере) публичной сети. Есть несколько универсальных веб-адресов, которые могут перенаправить вас на страницу входа в систему маршрутизатора сети. Итак, подключившись к сети Wi-Fi, включите свой веб-браузер (Safari, Google Chrome, Yandex бразуер, Firefox и т. д.) и введите в браузерной сроке имя routerlogin.net, нажав ввод. В большинстве случаев это поможет автоматически сделать перенаправление на страницу авторизации публичной сети, к которой вы подключились. И если это не сработает, попробуйте ввести поочередно эти веб-адреса:

  • https://localhost
  • Example.com
  • 8.8.8.8
  • neverssl.com
  • Captive.apple.com

Если ни один из вышеперечисленных способов не работает, выполните следующие действия в своем устройстве и повторите попытку:

  • Очистите кеш вашего браузера. Обычно это можно сделать из меню истории вашего браузера
  • Временно отключите все альтернативные DNS-серверы, которые вы используете, и вернитесь к настройкам по умолчанию (откатите устройство к заводским настройкам)

В данной статье мы разберем 4 способа как зарегистрировать нового пользователя: Сторонние сервисы авторизации (такие как Google), Авторизация с использованием токенов, Авторизация с помощью номера телефона, Логин + Пароль. Статья даст вам конкретный алгоритм реализации каждого способа. Необходимые библиотеки, а также примеры кода. Я постараюсь приводить в пример реализацию на чистейшем JavaScript, для того чтобы вы смогли внедрить функционал в свое проект, не зависимо от используемого фреймворка, однако также будут примеры для тандема Angular + Asp .Net Core. Мы обсудим как защитить ваш сайт от взлома. На сколько это сложно и возможно ли в принципе гарантировать 100% защиту. Итак, давайте приступим.

Регистрация. Аутентификация. Авторизация.

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

Начнем с процесса регистрации. Перед вами форма с несколькими полями: Имя, Логин, Пароль, Кличка вашей собаки и т.д. Вы покорно заполняете все поля со звездочками, после чего жмякаете на кнопку “Зарегистрироваться”. Ваши данные отправляются на сервер при помощи HTTP, сервер создает в базе данных новую запись, и если все проходит успешно, то вы зарегистрировались в системе. То есть процесс регистрации – это просто сохранение на сервере “в определенном текстовом файле” данных, которые вы заполнили на сайте.

Это пример самого простого способа регистрации, который только можно представить. В реальности так никогда не делают, но вот общий принцип неизменен. Более подробно, как происходит процесс регистрации в современных системах, мы разберем позднее, а сейчас давайте взглянем на процесс авторизации.

Когда вы заходите в свой аккаунт в социальной сети, то у вас отображаются только ваши фотографии, видео и посты. Тоже самое происходит, для любого другого человека и это не кажется странным. Но все данные, о том сколько у вас картинок, историю сообщений и даже рекомендации, которые заточены именно под вас, нужно где-то хранить. Хранить их нужно очевидно на сервере, т.к если сохранить эти данные в браузере, то они будут доступны вам, только с одного устройства (где вы регистрировались). Как уже было сказано, при регистрации, для каждого пользователя создается “файл” на жестком диске сервера, в котором будут храниться все данные. В момент авторизации, данные, введенного вами логина и пароля отправляются на сервер, где среди всех файлов, относящихся разным людям по логину ищется именно ваш, после чего проверяется соответствует ли отправленный пароль, тому который сохранен в файле и если да, то в браузер возвращаются необходимые данные пользователя. То есть процесс авторизации – это получение с сервера нужных данных о пользователе.

Разница между аутентификацией, идентификацией и авторизацией

По большому счету – это разные этапы одного процесса (предоставление доступа пользователю).

И хоть все эти этапы и разделяют, но обычно в процессе реализации – это могут быть просто 3 разных метода (функции), вызывающихся в приложении последовательно.

Разделение также нужно для тех случаев, если вы можете опустить какой-либо из этапов (и выполнить только 2 других). К примеру, пользователь прошел все 3 этапа и получил токен доступа. Токен подтверждает тот факт, что человек прошел аутентификацию, а значит при следующем обращении можно опустить этот этап. Backend приложение должно будет только проверить id пользователя (хранящийся в токене) и по id достать права.

Далее под словом “авторизация” (для простоты) будет подразумеваться весь процесс получение доступа.

Что представляет из себя база данных.

Выше я писал про чудесный “текстовый файл”, в котором хранятся все данные пользователей. Вы безусловно можете организовать хранение данных в обычных .txt файлах, но на практике так никто не делает. Данная формулировка была использована, для того чтобы вы понимали, что ваши данные хранятся на жестком диске, таким же образом, как вы храните у себя на компьютере фотки, записи и видео.

Но используют для этих целей определенные программы “Базы данных”. База данных – это программа, которая работает в фоновом режиме, функциями которой вы можете пользоваться из других программ (написанных вами). Что это за функции? – если коротко, то это операции сохранения и получения данных, но в отличии от обычного текстового файла, база данных выполняет операции сохранения и получение намного быстрее (Особенно когда этих данных становится очень много).

Таким образом работу backend приложения можно представить, как работу 2-х независимых программ:

  1. Серверное приложение – программа, которая отвечает за функционал сервера
  2. База данных – программа, которая отвечает за управление данными, и которую использует серверное приложение. При этом База данных не может использовать функционал серверного приложения.

Почему современные приложения не используют логин + пароль для авторизации.

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

Основной момент – обеспечение безопасности. Давайте взглянем на основные методы, с помощью которых злоумышленники могут получить доступ к вашему аккаунту:

  • Фишинг – хакеры могут создать копию сайта, на котором вы введете свой логин и пароль. После чего эти данные сохраняются на сервере злоумышленников, и они могут войти в ваш аккаунт используя их. Сюда же входят различные звонки от сотрудников банка, которые просят предоставить информацию.
  • Перебор паролей автоматическим программами.
  • Перехват трафика – для того чтобы залогиниться на сайте нужно отправить на сервер логин и пароль с помощью HTTP , которые могут быть перехвачены хакерами.
  • XSS – вставка на сайт вредоносного JS кода, который будет изменять логику приложения.

Какой бы метод авторизации вы не использовали он не спасет от взлома, если будут использованы фишинг или перебор паролей. Просто потому что в первом случае вы “по собственной воле” говорите свой пароль, а во втором этот пароль у вас “отгадывают”. Но в любом случае хакеры узнают ваши данные для входа в том виде, в котором используете их вы. А значит для приложения теперь вы ничем не отличаетесь (Ну разве что IP с которого будет происходить вход). Здесь единственная мера защиты – это смотреть на каком сайте вы вводите пароль и использовать сложный пароль. “Усовершенствованные” методы авторизации спасают именно в тех случаях, когда злоумышленники пытаются косвенно получить ваши данные (к примеру перехватом трафика).

В чем проблема авторизации при помощи логина + пароль

Для получения любых данных вашего пользователя нужно доказать серверу, что вы – это вы (введя пароль и отправив его на сервер). Таким образом, в такой модели авторизации web-приложение будет каждый раз обмениваться логином и паролем с сервером при необходимости, а это опасность перехвата. В дополнении к этому логин и пароль придется где-то хранить (Чтобы использовать их в последующих запросах к серверу. Иначе придется постоянно просить пользователя ввести пароль при переходе на новую страницу) – следовательно есть возможность получения доступа к этим данным в случае использования XSS.

Чтобы избежать данных проблем в процессе авторизации используют специальные ключи – токены, которые с одной стороны не содержат приватных данных (паролей), а с другой помогают серверу идентифицировать пользователя.

Использование токенов в процессе авторизации

Токен представляет из себя простую строку из символов, на примере этой:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYX QiOjE2Nzc5MTcxOTYsImV4cCI6MTcwOTQ1MzE5NiwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViI joianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2Nr ZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN 0IEFkbWluaXN0cmF0b3IiXX0.sBi4RpRuoIHRisficYOs3278nuu83ufS9ZUH-IkDGRs

Давайте кратко опишем этапы авторизации с помощью токена:

  1. Ввод логина и пароля.
  2. Шифрование (преобразование логина и пароля в закодированную строку).
  3. Передача шифрованных данных на сервер.
  4. Генерация сервером токена доступа, с помощью которого web-приложение будет обращаться к backend приложению для получения данных.
  5. Отправка токена обратно в браузер.
  6. Сохранение токена в локальном хранилище или в куки, для дальнейшего использования.

Суть здесь в том, что мы 1 раз передаем приватные данные по сети, после чего используем токен, который содержит только публичные данные.

Прежде чем погружаться в детали каждого этапа, давайте взглянем на то, какие типы авторизации с использованием токенов существуют. Все типы можно разделить на 2 группы, которые различаются способом генерации токена доступа:

Авторизация на самом сайте

В этом случае логин и пароль, вводятся на том сайте на котором вы сейчас находитесь, после чего они кодируются и отправляются на сервер, где генерируется токен и возвращается на сайт.

Авторизация на стороннем сервисе (Gmail).

Здесь пользователя перебрасывает на сторонний ресурс (открывается новая вкладка или окно браузера), где он вводит данные авторизации. Этот метод, отличается тем, что во-первых – это намного проще для пользователя. А во-вторых – не нужно вводить данные от вашего аккаунта (к примеру от аккаунта Google), на неизвестном сайте, который запрашивает регистрацию. Пользователь вводит свои данные, сторонний сервис (в нашем случае Gmail) генерирует токен доступа и отправляет его на тот сайт, с которого перешел пользователь. После чего сайт работает уже не с вашими авторизационными данными от сервиса, а с токеном.

Этапы такой авторизации описываются в стандартах – OAuth и OAuth 2.0. Обе версии описывают один и тот же алгоритм, но 2 версия – более защищенная.

Алгоритм авторизации – подробно.

  1. После того как пользователь ввел свои данные, то желательно их закодировать, чтобы не передавать по сети в простом текстовом виде. Здесь можно использовать любой алгоритм шифрования, можно даже закодировать в простую Base64 строку. Дело в том, что из браузера не получится зашифровать данные так, чтобы гарантировать их 100% безопасность при передаче по сети, т.к для этого нужно использовать какой-то ключ, который знает и сервер и браузер (чтобы первый смог закодировать, а второй декодировать). Но поскольку любые данные в браузере – публичные и при желании код в браузере можно посмотреть, то и этот ключ хакеры могут потенциально перехватить. Таким образом мы хоть и кодируем данные при передаче из браузера, но при желании и должных знаниях эту информацию можно узнать. Поэтому момент передачи логина и пароля связан с определенными рисками.
  2. Итак, авторизационные данные пришли на сервер. Бекенд приложение декодирует полученные данные и добавляет новую запись с вашими данными в БД (базу данных). После чего в ответ возвращается строка(токен). Особенность этой строки в том, что она закодирована при помощи уникального ключа, который известен, только бекенд приложению. Внутри этой строки закодированы какие-то данные и никто, кроме сервера (даже клиентское приложение), не может узнать что-это за данные (для этого нужен ключ).
  3. Токен возвращается на клиент и если в дальнейшем браузер захочет запросить данные, то он вместе с http запросом должен будет отправить токен, который будет декодирован на сервере, чтобы убедиться что вы это вы. И что токен не был изменен в процессе (если его изменить, то сервер не сможет декодировать его, что будет сигнализировать о потенциальной попытке взлома).
  4. Токен может передаваться любым способом. Вы можете поместить его в тело (Body) http запроса, передать через куки или в Header. Здесь цель просто доставить эту строку на сервер. При этом обычно токен отправляется как дополнительный заголовок хедера:

Host: net.tutsplus.com

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1

Authorization: {token}

А вот как выглядит реализация на Angular.

Для передачи токена используют хедер, потому что – это во-первых, удобнее, т.к вам не нужно модифицировать структуру каждого вашего запроса и помещать его в Body. А во-вторых, многие библиотеки, реализующие авторизацию, работают именно с хедером запроса.

JWT(JSON Web Token)

Как мы выяснили любой токен представляет из себя строку. И каждое приложение, которое реализует процесс авторизации, может на свое усмотрение использовать любую структуру токена. Но для браузерной авторизации чаще всего используют JWT токен. Это просто некоторый общепринятый стандарт.

Что представляет из себя этот стандарт ? Как можно догадаться из названия, этот стандарт основан на JSON и позволяет передавать вместе с токеном любой JSON объект (а поскольку мы можем любые данные представить в качестве объекта, который в последствии будет превращен в JSON, то внутри JWT можно передавать всё что угодно). JWT состоит из 3-х частей:

1) Header

2) Payload

3) Уникальный ключ, для шифрования

Получается у нас есть объект, состоящий из 3-х полей. В хедере мы указываем, что за тип токена мы используем и как будут кодироваться данные. В секции payload – данные, которые мы хотим передавать с сервера на клиент и обратно. А уникальный ключ – это пароль, с помощью которого мы кодируем 2 предыдущих части и превращаем их в строку.

Ключ, всегда хранится только на сервере. И клиентское приложение не имеет к нему доступа. Таким образом гарантируется, что изменить токен может только приложение у которого есть этот ключ (то есть только сервер). Здесь важно, что именно ИЗМЕНИТЬ, т.к декодировать токен и получить из него header и payload может любой, кто получил этот токен. Эти данные публичные.

Алгоритм генерации JWT токена на Java Script

Сначала мы превращаем header и payload в base64. Далее используем алгоритм шифрования из библиотеки CryptoJs, для того чтобы закодировать две полученные base64 строки и получить сигнатуру(которая тоже является строкой). После чего просто объединяем 3 полученные строки в одну, разделяя точками.

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

Access и Refresh токены

На данном этапе мы выяснили, что такое JWT, какую структуру он имеет, а также как происходит валидация токена. Хакеры не могут изменить данные нашего токена (и вставить к примеру свои). Но перехватить токен и использовать его для доступа к аккаунту, могут. Ведь токен содержит все нужные данные для авторизации и любой человек получивший к нему доступ, не будет отличаться для сервера от настоящего владельца аккаунта.

Для решения этой проблемы существуют Access и Refresh токены. Здесь мы не начинаем использовать какой-то новый способ авторизации. Используется все тот же JWT, но теперь единственный токен, который у нас был мы называем Access Token, при этом в дополнении к нему появляется второй Refresh токен, который также представляет из себя строку, имеет одинаковую структуру с Access Token, поэтому может хранить внутри какие-то данные (хоть и не обязательно и обычно это не требуется).

Важно то, что у Access и Refresh токенов появляются обязательные поля внутри их payload (iat, exp). Об их существовании я уже упоминал, но когда у нас есть только 1 токен, то эти поля по большому счету не используются и содержат дополнительную информацию.

Iat (issued at time) – время, когда токен сгенерирован.

Exp (expiration time) – время, до которого токен будет считаться валидным.

Алгоритм авторизации с использованием Refresh и Access токенов.

  1. Пользователь вводит логин и пароль. Они отправляются на сервер (Аналогично с использованием одного токена).
  2. Сервер создает/находит пользователя в Базе данных, после чего генерирует 2 токена (генерация происходит по уже известному алгоритму), но в этот раз добавляются iat и exp поля. При этом для Access Token, exp – устанавливается на короткий срок (15 -20 минут), а вот для Refresh Token, значение exp задается большим (несколько дней или недель).
  3. Далее сервер возвращает 2 токена в браузер, где они сохраняются в локальном хранилище.
  4. Теперь, если клиентское приложение хочет получить доступ к данным, то прежде чем отправлять запрос с Access Token в заголовке, нужно проверить не истек ли его срок жизни и если, нет, то отправлять запрос, если же токен expired, то прежде чем отправлять запрос нужно обновить токен (а иначе сервер получит не валидный токен и вернет ошибку).
  5. Для того чтобы обновить AccessToken, клиент отправляет специальный запрос, в котором отправляет Refresh Token. Сервер, получает этот Refresh Token и на его основе генерирует новую пару Access + Refresh токенов, которые возвращаются на клиент и опять сохраняются. Однако в случае, если при создании новой пары токенов, оказывается, что и RefreshToken уже устарел, то возвращается ошибка и пользователя просят еще раз ввести свой логин и пароль.

Почему нельзя обойтись одним Access токеном

Как мы ранее выяснили 1 токен защищает от ситуаций, когда хакеры меняют данные внутри токена (payload), но не защищают от того, что с похищенным токеном злоумышленник может получить доступ к аккаунту пользователя. Refresh Token частично решает эту проблему.

Давайте разберемся что у нас произойдет, если ваши токены похищены. Хакер получил доступ к вашему аккаунту и может делать все что угодно, до тех пор пока вы не зайдете в систему. Потому что в этот момент истечет срок действия вашего Access токена и вам придется обновить пару токенов на новую, следовательно похищенные токены станут не валидными. Или представим др. ситуацию. Хакер провел долгое время на вашей странице, а значит требуется обновить Access Token с его стороны (что он успешно сделает), ведь он завладел обеими (в том числе и Refresh). Следовательно, теперь уже когда вы попытаетесь зайти в свой аккаунт сервер вернет ошибку, т.к уже ваш Refresh Token не валидный, после чего вы введете свои данные и не валидной станет пара токенов, похищенная злоумышленником.

Таким образом, Access и Refresh токены не защищают полностью от взлома, но сильно усложняют жизнь взломщикам (т.к похищенный токен нельзя долго использовать).

Где хранить токены

Есть 2 популярных варианта Local Storage и куки (либо внутри сессионного хранилища). И хранить пару Access и Refresh токенов лучше в куки. Это обосновано тем, что если на сайт встроят вредоносный код, то через JS хакеры могут получить доступ к Local Storage, но вот куки не хранятся в локальном хранилище браузера, они передаются с запросом. Соответственно, для того чтобы получить к ним доступ, нужно сделать как минимум один запрос авторизации. (с неизвестными логином и паролем).

Хотя существуют методики и для хищения данных из куки. Здесь нужно запомнить один момент. У вас не получится на 100% защититься от всех атак в браузере, но чем больше уровней защиты вы установите, тем меньше вероятность взлома.

Авторизация через внешние сервисы

Общий алгоритм добавления авторизации через сторонние сервисы следующий:

  1. Вам нужно сделать редирект со своего сайта на сайт сервиса.
  2. Дождаться пока пользователь введет там свои данные и сервис сгенерирует токен авторизации.
  3. Дождаться HTTP respons-а от стороннего сервиса и получить токен доступа (внутри которого хранятся данные о пользователе).
  4. Отправить полученный токен уже на собственный сервер и сгенерировать пару Access + Refresh токен на основе данных пользователя. После чего сохранить их в браузере.
  5. А далее идет обычный flow с JWT авторизацией, описанный выше.

А теперь на примере Gmail авторизации давайте взглянем на детали:

В Gmail, ровно как и в других похожих сервисах первое что вам нужно будет сделать – это создать “Приложение” для вашего сайта на специальном сервисе для разработчиков. У каждого сервиса авторизации он свой. Для Google – это Developer Console. Как зарегистрировать профиль, создать приложение и получить ключ можно прочитать здесь.

Как вы могли догадаться целью создания профиля является получение этого самого ключа. У гугл он называется Client Id. Client Id будет использоваться в нашем frontend приложении. Вот как это может выглядеть на TypeScript:

HTML

<button>Sign In with Google</button>

Type Script

DIALOG_PARAMS – настройки окна, где пользователь будет вводить авторизационные данные.

googleAuthListener – слушает сообщения от GMail и в случае успешной авторизации возвращает ответ с кодом авторизации (это не тоже самое что токен, но с его помощью можно получить токен).

dialogUrl – URL на который переходит пользователь для ввода логина и пароля.

Получилось довольно громоздко, но есть укороченная версия. Вот к примеру реализация, если вы используете фреймворк Angular.

Авторизация по номеру телефона

Авторизация по номеру телефона почти идентична обычной с использованием логина и пароля с той лишь разницей, что теперь вместо email мы используем номер, а вместо пароля, одноразовый проверочный код. На этом моменте не нужно долго останавливаться.

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

Сервисы для отправки Email и СМС сообщений.

Начнем с отправки email. Чтобы отправить сообщение на почту вам необходим SMTP сервер (и без него обойтись не получится). Здесь есть 2 варианта:

Вариант 1 – сложный. Вы создаете отдельный свой сервер и настраиваете его, чтобы он понимал SMTP протокол. В большинстве случаев это слишком сложно и излишне.

Вариант 2 – рациональный. Вы используете сторонние сервисы, которые берут на себя работу по обслуживанию SMTP сервера, а вам предоставляют, либо готовый API для отправки сообщений, либо сам адрес SMTP сервера, который вы можете использовать.

Как вы могли догадаться, в обоих случаях удовольствие это не бесплатное. Или почти не бесплатное. В случае с SMTP сервисами, многие провайдеры предоставляют триал или бесплатное использование на время разработки (то есть у вас все будет работать, но только на маленьких нагрузках). Одним из таких сервисов является SMTP.bz.

Для того чтобы отправить email с помощью этого сервиса, нужно зарегистрироваться и привязать домен вашего сайта (на сервисе есть инструкция), после чего вам выдаются логин, пароль, адрес и порт от сервера, которые нужны для подключения к SMTP. Приведу небольшой кусок кода (на C#), как отправить Email используя SMTP сервер.

Теперь разберемся с сервисами для отправки СМС сообщений. В этом случае у нас также есть готовые API для отправки смс. Например — smsc.ru. Использование довольно простое – отправка http запроса с номером телефона и сообщением.

Однако в данном случае я не нашел сервисов, у которых есть бесплатные периоды (Напишите в комментариях если вы знаете такие) Возможно это связано с тем, что в цепочке отправки смс также участвует сотовый оператор, который взымает плату за отправку с “смс сервисов”. Потому они не могут предоставить бесплатный триал доступ, как в случае с SMTP.

А нужна ли вам вообще авторизация на сайте ?

Любая авторизация – это очень очень сложно для пользователя. Поэтому по возможности не надо донимать регистрацией. Если у вас лендинг, блог или информационный сайт, который не подразумевает личного кабинета и уровней доступа, то вообще не делайте авторизацию. Потому что а зачем она вам ?

Заканчиваем

Для закрепления материала вы можете скачать готовый проект, в котором реализованы все виды авторизации описанные в статье. А также попробовать что-то поменять под себя. Надеюсь статья была исчерпывающей, если нет, то напишите в комментариях что я мог упустить.

Понравилась статья? Поделить с друзьями:
  • Как найти светящиеся кроссовки
  • Как найти в моем компьютере сервис
  • Как найти сонник миллера
  • Как найти форматирование в ворде
  • Как найти сварной шов