Http авторизация basic – Аутентификация и авторизация в микросервисных приложениях / DataArt corporate blog / Habr

Содержание

HTTP авторизация - Веб-технологии для разработчиков

HTTP предоставляет набор инструментов для разграничения доступа к ресурсам и авторизацией. Самой распространенной схемой HTTP авторизации является "Basic" (базовая) авторизация. Данное руководство описывает основные возможности HTTP авторизации и показывает способы ограничения доступа к вашему серверу с ее использованием.

Общий механизм HTTP авторизации

RFC 7235 определяет средства HTTP авторизации, которые может использовать сервер для запроса у клиента аутентификационной информации. Сценарий запрос-ответ подразумевает, что вначале сервер отвечает клиенту со статусом 401 (Unauthorized) и предоставляет информацию о порядке авторизации через заголовок WWW-Authenticate, содержащий хотя бы один метод авторизации. Клиент, который хочет авторизоваться, может сделать это, включив в следующий запрос заголовок Authorization с требуемыми данными. Обычно, клиент отображает запрос пароля пользователю, и после получения ответа отправляет запрос с пользовательскими данными в заголовке Authorization.

В случае базовой авторизации как на иллюстрации выше, обмен 

должен вестись через HTTPS (TLS) соединение, чтобы обеспечить защищённость.

Прокси-авторизация

Этот же механизм запроса и ответа может быть использован для прокси-авторизации. В таком случае ответ посылает промежуточный прокси-сервер, который требует авторизации. Поскольку обе формы авторизации могут использоваться одновременно, для них используются разные заголовки и коды статуса ответа. В случае с прокси, статус-код запроса 407 (Proxy Authentication Required) и заголовок Proxy-Authenticate, который содержит хотя бы один запрос, относящийся к прокси-авторизации, а для передачи авторизационных данных прокси-серверу используется заголовок Proxy-Authorization.

Access forbidden

Если (прокси) сервер получает корректные учетные данные которые не подходят для доступа к данному ресурсу, сервер должен отправить ответ со статус кодом 403 Forbidden. В отличии от статус кода 401 Unauthorized или 407 Proxy Authentication Required, аутетификация для этого пользователя не возможна.

WWW-Authenticate
and Proxy-Authenticate headers

The WWW-Authenticate and Proxy-Authenticate response headers define the authentication method that should be used to gain access to a resource. They need to specify which authentication scheme is used, so that the client that wishes to authorize knows how to provide the credentials. The syntax for these headers is the following:

WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>

Here, <type> is the authentication scheme ("Basic" is the most common scheme and introduced below). The realm is used to describe the protected area or to indicate the scope of protection. This could be a message like "Access to the staging site" or similar, so that the user knows to which space they are trying to get access to.

Authorization and Proxy-Authorization headers

The Authorization and Proxy-Authorization request headers contain the credentials to authenticate a user agent with a (proxy) server. Here, the type is needed again followed by the credentials, which can be encoded or encrypted depending on which authentication scheme is used.

Authorization: <type> <credentials>
Proxy-Authorization: <type> <credentials>

Authentication schemes

The general HTTP authentication framework is used by several authentication schemes. Schemes can differ in security strength and in their availability in client or server software.

The most common authentication scheme is the "Basic" authentication scheme which is introduced in more details below. IANA maintains a list of authentication schemes, but there are other schemes offered by host services, such as Amazon AWS. Common authentication schemes include:

Basic authentication scheme

The "Basic" HTTP authentication scheme is defined in RFC 7617, which transmits credentials as user ID/password pairs, encoded using base64.

Security of basic authentication

As the user ID and password are passed over the network as clear text (it is base64 encoded, but base64 is a reversible encoding), the basic authentication scheme is not secure. HTTPS / TLS should be used in conjunction with basic authentication. Without these additional security enhancements, basic authentication should not be used to protect sensitive or valuable information.

Restricting access with Apache and basic authentication

To password-protect a directory on an Apache server, you will need a .htaccess and a .htpasswd file.

The .htaccess file typically looks like this:

AuthType Basic
AuthName "Access to the staging site"
AuthUserFile /path/to/.htpasswd
Require valid-user

The .htaccess file references a .htpasswd file in which each line contains of a username and a password separated by a colon (":"). You can not see the actual passwords as they are encrypted (md5 in this case). Note that you can name your .htpasswd file differently if you like, but keep in mind this file shouldn't be accessible to anyone. (Apache is usually configured to prevent access to .ht* files).

aladdin:$apr1$ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz.
user2:$apr1$O04r.y2H$/vEkesPhVInBByJUkXitA/

Restricting access with nginx and basic authentication

For nginx, you will need to specify a location that you are going to protect and the

auth_basic directive that provides the name to the password-protected area. The auth_basic_user_file directive then points to a .htpasswd file containing the encrypted user credentials, just like in the Apache example above.

location /status {                                       
    auth_basic           "Access to the staging site";
    auth_basic_user_file /etc/apache2/.htpasswd;
}

Access using credentials in the URL

Many clients also let you avoid the login prompt by using an encoded URL containing the username and the password like this:

https://username:[email protected]/

The use of these URLs is deprecated. In Chrome, the username:[email protected] part in URLs is even stripped out for security reasons. In Firefox, it is checked if the site actually requires authentication and if not, Firefox will warn the user with a prompt "You are about to log in to the site “www.example.com” with the username “username”, but the website does not require authentication. This may be an attempt to trick you.".

See also

developer.mozilla.org

HTTP Basic Authentication или HTTP авторизация « Все о WEB программировании

Ромчик

5

Доброго времени суток. В данной статье мы остановимся на таком понятии как http basic authentication или http авторизация. Для чего нужна http basic authentication и как настроить http авторизацию. И в качестве примера мы сделаем HTTP авторизацию для админки WordPress. Ну что поехали.

Первое, что мы сделаем – это разберемся с понятием http авторизации.

HTTP authentication

HTTP authentication – это протокол, описанный в стандартах  HTTP 1.0/1.1. Работает следующим образом:

  1. При обращении неавторизованного пользователя к защищенному ресурсу сервер возвращает «401 Unauthorized» и добавляет заголовок «WWW-Authenticate»
  2. Браузер при получении ответа с заголовком «WWW-Authenticate» выкидывает форму для ввода логина и пароля. И в дальнейшем при обращении к данному ресурсу передает заголовок «Authorization», где хранятся данные пользователя для аутентификации.

Существуют несколько схем  http авторизации:

  • Basic
  • Digest
  • NTLM
  • Negotiate

Главное отличие – это уровень безопасности. Мы остановимся на basic – это самая небезопасная схема. Но при использовании HTTPS, является относительно безопасным.

Схема Basic является наиболее простой схемой, при которой логин и пароль передаются в заголовке «Authorization» в незашифрованном виде.

HTTP авторизация для админки WordPress

Если вы используете SSL на своем сайте, то вы можете дополнительно настроить http basic authentication для админки WordPress. А это дополнительная защита.

Небольшое отступление: у меня ОС Windows 10 и OpenServer, который расположен по адресу e:\OpenServer\

Первое, что нам необходимо сделать – это создать файл .htpasswd

Затем перейти на один из сервисов генерации пароля (или воспользоваться утилитой htpasswd у кого Linux), например https://truemisha.ru/tools/htpasswd-generator И сгенерировать пароль

генерация пароля для http авторизации

Скопируем строку и вставим в только что созданный файл .htpasswd


Admin:$apr1$grwacq2z$g1Z5bNYkD0vJKF2HllrRw/

Отлично. Теперь необходимо настроить apache с помощью файла .htaccess.

Переходим в каталог с админкой, по умолчанию это wp-admin и в нем создаем файл .htaccess.

И в него помещаем следующий код:


AuthType Basic
AuthName "Input username and password"
AuthUserFile e:\OpenServer\.htpasswd
Require valid-user

Где в AuthName указываем текст сообщения, в AuthUserFile указываем путь к файлу .htpasswd.

Сохраняем и проверяем.

При попытке перейти к админке WordPress сервер запросит http авторизацию.

http basic authentication

Если мы не введем логин и пароль, то сервер вернет ошибку «Authentication required»

сообщение об ошибке автоизации

Вводим логин и пароль (Логин: Admin, а пароль: admin)

страница авторизации WordPress

И нас пустило на стандартную страницу авторизации.

И видео к данной статье:

Заключение

Мы с вами дополнительно защитили админку WordPress http авторизацией. Но помните, что мы использовали http basic authentication, а данный тип передает логин и пароль в незашифрованном виде. Используйте https. А в следующей статье мы рассмотрим как организовать http авторизацию с помощью плагина для WordPress (когда у нас нет доступа к настройкам apache). Так, что не пропускайте выхода новых статей подписавшись: VK, facebook, twitter

Понравилась статья? Поделись с друзьями.

web-programming.com.ua

Apache: Basic/Digest авторизация · [email protected]

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

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

Настройка авторизации

Basic

  1. Создаем новый файл (флаг -с) с пользователем admin
sudo htpasswd -c /usr/local-conf/.htpasswd admin

Вводим и подтверждаем пароль для пользователя 'admin', например 'qwe123'. В каталоге /usr/local-conf/ появится новый файл .htpasswd

  1. Подключаем модуль apache, отвечающий за basic-авторизацию
  1. Вы настройках хоста (можно виртуального) добавляем
<Directory /var/www/tests/basic>
  AuthType Basic
  AuthName "private"
  AuthUserFile /usr/local-conf/.htpasswd
  Require valid-user
</Directory>

На что здесь следует обратить внимание: необходимо запретить внешний доступ к чтению файла .htpasswd. Для этого файл следует размещать за пределами каталога сайта.

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

  1. Перезапускаем apache

Digest

  1. Создаем новый файл (флаг -с) пароля
sudo htdigest -c /usr/local-conf/.htpasswd private admin

Обратите внимание: здесь при создании нового пользователя в защищенную зону необходимо вводить псевдоним этой зоны (в отличии от basic)

  1. Подключаем модуль apache, отвечающий за digest-авторизацию
  1. В настройках хоста (можно виртуального) добавляем
<Directory /var/www/tests/digest>
        AuthType Digest
        AuthName private
        AuthUserFile /usr/local-conf/.htpasswd
        Require valid-user
</Directory>

Обратить внимание: здесь обязательно в параметре AuthName нужно указывать псевдоним защищенной зоны указанный нами на шаге 1

  1. Перезапускаем apache

Как работает авторизация

Basic

Когда мы пытаемся зайти на страницу защищенной области (GET-запрос по адресу http://tests/basic/index.html), происходит следующее

  1. Браузер отправляет серверу запрос примерно с таким заголовком
GET /basic/ HTTP/1.1
Host: tests
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36
HTTPS: 1
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
  1. Сервер возвращает ответ
HTTP/1.1 401 Unauthorized
Date: Sun, 18 Sep 2016 09:16:25 GMT
Server: Apache/2.4.7 (Ubuntu)
WWW-Authenticate: Basic realm="Private Area"
Content-Length: 451
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h2>Unauthorized</h2>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.7 (Ubuntu) Server at tests Port 80</address>
</body></html>

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

  1. Если мы вводим неправильный логин-пароль, браузер генерирует и отправляет сообщение примерно со следующим заголовком
GET /basic/ HTTP/1.1
Host: tests
Connection: keep-alive
Cache-Control: max-age=0
Authorization: Basic YXNtaXY6ZGRk
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36
HTTPS: 1
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4

Обратите внимание на ключ Authorization - браузер кодирует (вроде бы) Ваш логин-пароль и тут же сохраняет его у себя. К данному факту мы еще вернемся позже

  1. Ответ сервера такой же, что и на шаге 2
  2. Если мы вводим правильный логин-пароль, то получаем от сервера примерно такой ответ
HTTP/1.1 200 OK
Date: Sun, 18 Sep 2016 09:44:30 GMT
Server: Apache/2.4.7 (Ubuntu)
Last-Modified: Sun, 18 Sep 2016 08:31:37 GMT
ETag: "c2-53cc406177934-gzip"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 161
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

В теле ответа передается для отображения в браузере загружаемая страница (index.html) И, внимание! Если страница ссылается на другие файлы (скрипты, стили и т.д.), находящиеся внутри защищаемой папки (basic), то браузер автоматически для каждого такого файла отправляет на сервер запросы с заголовками, аналогичными шагу 3.

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

Digest

Схема авторизации аналогична Basic. Отличие лишь в параметрах, перезаваемых в заголовках запросов и ответов.

Ответ сервера о необходимости прохождения авторизации (шаг 2)

WWW-Authenticate: Digest realm="private", nonce="lz9uTMU8BQA=398ac33371c9922a84e12c06394493152781e575", algorithm=MD5, qop="auth"

Запрос клиента с введенными значениями логина и пароля (шаг 3)

Authorization: Digest username="admin", realm="private", nonce="bT2bUMU8BQA=c7efe86ce4147b1ada766fbcd96639c521855b45", uri="/digest/", algorithm=MD5, response="bf1ec1979946c684cbe834974be19dc9", qop=auth, nc=00000001, cnonce="896733f4c19f6c9d"

Ответ сервера об успешном прохождении авторизации (шаг 5)

Authentication-Info: rspauth="c7fa3bfe108be8c47a6fad4b4a0f8125", cnonce="896733f4c19f6c9d", nc=00000001, qop=auth

Теперь разберемся почему Basic и Digest авторизация сегодня считается ненадежной и насколько она ненадежна.

Надежность авторизации

Basic

Прежде всего логин и пароль пользователя хранятся на компьютере пользователя и передаются серверу (шаг 3) БЕЗ шифрования. То что мы видим в заголовке запроса

Authorization: Basic YXNtaXY6ZGRk
  • это всего лишь кодирование base64. Преобразовать набор символов в пару логин-пароль не составляет никакого труда, например так https://www.base64decode.org/

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

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

Digest

Работа Digest авторизации чуть сложнее. Прежде всего, при первом сообщении клиенту о необходимости прохождения авторизации (шаг 2), сервер передает в заголовке ряд параметров

WWW-Authenticate: Digest realm="private", nonce="lz9uTMU8BQA=398ac33371c9922a84e12c06394493152781e575", algorithm=MD5, qop="auth"
  • realm - имя защищенной области (помните, мы акцентировали на ней внимание при настроке файла конфигурации?) Здесь значение этого параметра играет роль (в отличии от Basic авторизации)
  • nonce - уникальный ключ, генерируемый сервером в момент отправки сообщения клиенту
  • algorithm - название алгоритма (как правило, MD5)

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

Пользователь вводит логин-пароль, браузер шифрует их и отправляет серверу для проверки следующую информацию (шаг 3)

Authorization: Digest username="admin", realm="private", nonce="bT2bUMU8BQA=c7efe86ce4147b1ada766fbcd96639c521855b45", uri="/digest/", algorithm=MD5, response="bf1ec1979946c684cbe834974be19dc9", qop=auth, nc=00000001, cnonce="896733f4c19f6c9d"

Здесь прежде всего нужно обратить внимание на параметр response. Это - контрольная сумма с которой будет сверяться сервер.

Получив от клиента информацию, сервер берет из файла паролей (.htpasswd) для пользователя username и защищенной зоны realm правильное значение пароля, по известному алгоритму (см. ниже) вычисляет контрольную сумму и сравнивает ее с суммой, переданной в response. Если суммы не совпадают - сервер вновь предлагает пройти авторизацию

Алгоритм расчета контрольной суммы (response) одинаков для клиента и сервера. Достаточно понятно от описан здесь

Таким образом, главное отличие Digest-авторизация - шифрование пароля. Что, впрочем не до конца исключает уязвимость данного способа авторизации.

Итоги

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

Безопасность

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

Подбор пароля основан на том, что basic и digest авторизация в чистом виде не контролируют количество неудачных попыток авторизации. Поэтому достаточно просто создать программу, автоматически генерирующую запросы доступа в защищенную с подставлением различных паролей (из заранее подготовленного словаря) до тех пор пока один из паролей не подойдет

Другой способ - взлом пароля реализуется в два этапа. Сначала необходимо получить информацию о логине-пароле пользователя (из данных сохраненных браузером клиента или перехваченного трафика). Затем из полученной информации извлекается пароль. Если для basic-авторизации это труда не составляет, то с digest-авторизацией сложнее. Но вполне осуществимо. Здесь применяется программное обеспечение использующее различные подходы:

  • прямой подбор паролей из словаря - наименне эффективный метод но при удачно составленном словаре вполне действенный (см пример ниже)
  • использование "радужных таблиц"
  • метод "туннелирования"
  • используя вычислительные мощности отдельных видов видеокарт

Подбор пароля из словаря

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

crunch 3 6  -f charset.lst mixalpha-numeric-all -o dict3-6.txt

Эта команда сгенерирует файл с паролями длиной от 3 до 6 символов с использованием предустановленного словаря mixalpha-numeric-all (все латинские буквы, цифры и нектороные символы). Правда, количество таких паролей будет 697.287.726.760 и занимать на диске они будут около 4 TB. Поэтому, на практите эту утилиту можно использовать только в случае каких либо сведений о пароле, например, что пароль состоит из 8 символов и только из цифр.

Так можно попытаться взломать пароль, перебрав 9.000.000 паролей. Полный перебор займет всего 1 минуту

# -*- coding: utf-8 -*-
import hashlib
def calc(h2,h3, nonce, cnonce):
    return hashlib.md5(h2+':'+nonce+':'+nc+':'+cnonce+':'+qop+':'+h3).hexdigest()

if __name__=='__main__':

    #данные о пароле из перехваченного трафика
    nonce="Z97svNM8BQA=71be2e3910ee86fa54a3e4afc13f5b9ecc02303b"
    qop="auth"
    nc="00000001"
    cnonce="ad82cf9261fe82d8"
    username='admin'
    realm='private'
    method='GET'
    uri='/digest/'
    TEMPLATE_RESP='9b8b18ff554a7e93f37d3e2b82dc40d0'

    h3=hashlib.md5(method+':'+uri).hexdigest()


    f=open('9mil.txt', 'r')
    for passwd in f:
        h2=hashlib.md5(username+':'+realm+':'+passwd[:-1]).hexdigest()
        resp=calc(h2,h3, nonce, cnonce)
        if resp==TEMPLATE_RESP:
            print 'Пароль - '+ passwd
            break

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

sudo tcpdump -A -s 1024 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' -i lo

Усиление защищенности Basic/Digest авторизации

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

Будем использовать возможности wsgi. Конфигурацию хоста в части авторизации настраиваем так

<Directory "c:/Apache24/htdocs/test/digest">
  AuthType Digest
  AuthName "orivate"
  Require valid-user
  #AuthUserFile "c:/.ht_digest"
  AuthDigestProvider wsgi
  WSGIAuthUserScript "c:/Apache24/cgi-bin/auth.wsgi"
</Directory>

Теперь прохождением авторизации будет управлять скрипт auth.wsgi. Скрипт должен быть примерно такого содержания

import md5
def get_realm_hash(environ, user, realm):
    value = md5.new()
    value.update('%s:%s:%s' % (user, realm, 'qwe123'))
    hash = value.hexdigest()

    # теперь легко логировать попытки авторизации
    #f=open('wsgi_auth.log','a')
    #f.write(str(environ['REMOTE_ADDR'])+'\t'+user+'\t'+realm+'\r')
    #f.close()

    if user == 'admin':
        return hash
    return None

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

Что касается защиты пароля от взлома ...


zlukfo.bitbucket.io

basic авторизация с капчей / Habr

Для приготовления авторизации с капчей нам понадобится сам nginx и его плагины encrypted-session, form-input, ctpp2, echo, headers-more, auth_request, auth_basic, set-misc. (Я дал ссылки на свои форки, т.к. делал некоторые изменения, которые пока не удалось пропихнуть в оригинальные репозитории. Можно также воспользоваться готовым образом.)

Для начала зададим
encrypted_session_key "abcdefghijklmnopqrstuvwxyz123456";

Дальше, на всякий случай, отключаем авторизационный заголовок
more_clear_input_headers Authorization;

Теперь защищаем всё авторизацией
auth_request /auth;
location =/auth {
    internal;
    subrequest_access_phase on; # разрешаем авторизационную фазу в подзапросе
    auth_request off; # не использовать авторизацию
    set_decode_base64 $auth_decode $cookie_auth; # раскодируем авторизационную куку
    set_decrypt_session $auth_decrypt $auth_decode; # расшифровываем авторизационную куку
    if ($auth_decrypt = "") { return 401 UNAUTHORIZED; } # если не удалось расшифровать, то значит пользователь не авторизован
    more_set_input_headers "Authorization: Basic $auth_decrypt"; # подменить авторизацию на basic (чтобы использовать переменную $remote_user)
    auth_basic_user_file /data/nginx/.htaccess; # задаём файл basic авторизации
    auth_basic Auth; # включаем basic авторизацию
    echo -n OK; # пользователь авторизован
}

Для авторизованных пользователей показываем контент из их папки
location / {
    alias html/$remote_user/;
}

А при отсутствии авторизации показываем авторизационную форму с капчей
error_page 401 = @error401;
location @error401 {
    set_escape_uri $request_uri_escape $request_uri; # кодируем запрос
    return 303 /login?request_uri=$request_uri_escape; # перенаправляем на авторизационную форму с капчей, сохранив запрос
}
location =/login {
    default_type "text/html; charset=utf-8"; # задаём тип
    if ($request_method = GET) { # если только показать авторизационную форму с капчей
        template login.html.ct2; # задаём шаблон
        ctpp2 on; # включаем шаблонизатор
        set_secure_random_alphanum $csrf_random 32; # задаём случайное csrf
        encrypted_session_expires 300; # задаём время жизни csrf 5 минут (5 * 60 = 300)
        set_encrypt_session $csrf_encrypt $csrf_random; # зашифровываем случайное csrf
        set_encode_base64 $csrf_encode $csrf_encrypt; # кодируем зашифрованное csrf
        add_header Set-Cookie "CSRF=$csrf_encode; Max-Age=300"; # помещаем зашифрованное csrf в куку на 5 минут (5 * 60 = 300)
        return 200 "{\"csrf\":\"$csrf_random\"}"; # возвращаем json для шаблонизатора
    } # иначе - обработать авторизационную форму с капчей
    set_form_input $csrf_form csrf; # получаем csrf из формы
    set_unescape_uri $csrf_unescape $csrf_form; # раскодируем csrf из формы
    set_decode_base64 $csrf_decode $cookie_csrf; # раскодируем csrf из куки
    set_decrypt_session $csrf_decrypt $csrf_decode; # расшифровываем csrf из куки
    if ($csrf_decrypt != $csrf_unescape) { return 303 $request_uri; } # если csrf из формы не совпадает с csrf из куки, то перенаправить на показ формы снова
    set_form_input $captcha_form captcha; # получаем капчу из формы
    set_unescape_uri $captcha_unescape $captcha_form; # раскодируем капчу из формы
    set_md5 $captcha_md5 "secret${captcha_unescape}${csrf_decrypt}"; # считаем md5
    if ($captcha_md5 != $cookie_captcha) { return 303 $request_uri; } # если md5 не совпадает с капчей из куки, то перенаправить на показ формы снова
    set_form_input $username_form username; # получаем логин из формы
    set_form_input $password_form password; # получаем пароль из формы
    set_unescape_uri $username_unescape $username_form; # раскодируем логин из формы
    set_unescape_uri $password_unescape $password_form; # раскодируем пароль из формы
    encrypted_session_expires 2592000; # задаём время жизни сессии 30 дней (30 * 24 * 60 * 60 = 2592000)
    set $username_password "$username_unescape:$password_unescape"; # задаём basic авторизацию
    set_encode_base64 $username_password_encode $username_password; # кодируем basic авторизацию
    set_encrypt_session $auth_encrypt $username_password_encode; # зашифровываем basic авторизацию
    set_encode_base64 $auth_encode $auth_encrypt; # кодируем зашифрованную basic авторизацию
    add_header Set-Cookie "Auth=$auth_encode; Max-Age=2592000"; # помещаем зашифрованную basic авторизацию в авторизационную куку на 30 дней (30 * 24 * 60 * 60 = 2592000)
    set $arg_request_uri_or_slash $arg_request_uri; # копируем запрос из аргумента
    set_if_empty $arg_request_uri_or_slash "/"; # если аргумент не задан, то начало
    set_unescape_uri $request_uri_unescape $arg_request_uri_or_slash; # раскодируем запрос
    return 303 $request_uri_unescape; # перенаправляем на сохранённый запрос
}

login.html
<html>
    <body>
        <form method="post">
            <input type="hidden" name="csrf" value="<TMPL_var csrf>" />
            username: <input type="text" name="username" placeholder="Enter User Name..." /><br />
            password: <input type="password" name="password" /><br />
            captcha: <img src="/captcha?csrf=<TMPL_var csrf>"/><input type="text" name="captcha" autocomplete="off" /><br />
            <input type="submit" name="submit" value="submit" />
        </form>
    </body>
</html>

habr.com

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *