Verification: a143cc29221c9be0

Php basic auth не работает

Php basic auth не работает

Введение

Многие веб-приложения предоставляют своим пользователям возможность аутентифицироваться в приложении и «войти в систему». Реализация этого функционала в веб-приложениях может быть сложной и потенциально рискованной задачей. По этой причине Laravel стремится предоставить вам инструменты, необходимые для быстрой, безопасной и простой реализации аутентификации.

По своей сути средства аутентификации Laravel состоят из «охранников» и «провайдеров». Охранники определяют, как пользователи проходят проверку подлинности для каждого запроса. Например, Laravel поставляется с охранником session, который поддерживает состояние, используя хранилище сессий и файлы Cookies.

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

Файл конфигурации аутентификации вашего приложения находится в config/auth.php. Этот файл содержит несколько хорошо задокументированных вариантов для настройки поведения служб аутентификации Laravel.

Охранников и провайдеров не следует путать с «ролями» и «разрешениями». Чтобы узнать больше об авторизации действий пользователя с помощью разрешений, обратитесь к документации по авторизации.

Стартовые комплекты

Хотите быстро начать работу? Установите стартовый комплект приложения в новое приложение Laravel. После миграции базы данных перейдите в браузере по адресу /register или любому другому URL-адресу вашего приложения. Стартовые комплекты возьмут на себя создание всей вашей системы аутентификации!

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

Рекомендации по базе данных

По умолчанию Laravel содержит модель Eloquent App\Models\User в вашем каталоге app/Models. Эта модель использует по умолчанию драйвер аутентификации eloquent. Если ваше приложение не использует Eloquent, то вы можете использовать драйвер аутентификации database, основанный на построителе запросов Laravel.

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

Кроме того, вы должны убедиться, что ваша таблица users (или эквивалентная) содержит столбец remember_token с параметрами VARCHAR(100) NULL. Этот столбец будет использоваться для хранения токена для пользователей, которые выбирают опцию «Запомнить меня» при входе в ваше приложение. Опять же, миграция таблицы пользователей по умолчанию, которая включена в новые приложения Laravel, уже содержит этот столбец.

Обзор экосистемы

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

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

Когда удаленной службе необходимо пройти аутентификации для доступа к API, файлы cookie обычно не используются для проверки подлинности, поскольку веб-браузер отсутствует. Вместо этого удаленная служба отправляет API-токен при каждом запросе к API. Приложение может проверять входящий токен по таблице допустимых API-токенов и «аутентифицировать» запрос как выполняемый пользователем, связанным с этим API-токеном.

Службы Web-аутентификации Laravel из коробки

Laravel содержит встроенные службы аутентификации и сессии, которые обычно доступны через фасады Auth и Session. Этот функционал обеспечивают аутентификацию на основе файлов Cookies для запросов, которые инициируются из веб-браузеров. Они предоставляют методы, которые позволяют вам проверять учетные данные пользователя и аутентифицировать пользователя. Кроме того, эти службы автоматически сохраняют необходимые данные аутентификации в сессии пользователя и выдают cookie сессии пользователя. В этой документации содержится информация о том, как использовать эти службы.

Стартовые комплекты приложения

Как уже было написано в этой документации, вы можете взаимодействовать с этими службами аутентификации напрямую, чтобы создать собственный слой аутентификации вашего приложения. Однако, чтобы помочь вам быстрее приступить к работе, мы выпустили бесплатные пакеты, которые обеспечивают надежную и современную основу всего слоя аутентификации. Это пакеты Laravel Breeze, Laravel Jetstream и Laravel Fortify.

Laravel Breeze – это простая, минимальная реализация всех возможностей аутентификации Laravel, включая вход в систему, регистрацию, сброс пароля, подтверждение электронной почты и подтверждение пароля. Слой представления Laravel Breeze состоит из простых шаблонов Blade, стилизованных с помощью Tailwind CSS. Чтобы начать использование, ознакомьтесь с документацией по стартовым комплектам.

Laravel Fortify – это лишь серверная часть аутентификации для Laravel, которая реализует многие возможности, описанные в этой документации, включая аутентификацию на основе файлов cookie, а также другие возможности, такие как двухфакторная аутентификация и проверка электронной почты. Fortify обеспечивает серверную реализацию аутентификации для Laravel Jetstream, но может использоваться и независимо в сочетании с Laravel Sanctum для обеспечения одностраничных приложений (SPA) возможностью аутентификацией с Laravel.

Laravel Jetstream – это надежный стартовый комплект, который использует и предлагает службы аутентификации Laravel Fortify, но с красивым современным пользовательским интерфейсом на основе Tailwind CSS, Livewire и / или Inertia.js. Laravel Jetstream дополнительно включает поддержку двухфакторной аутентификации, поддержку команды, управление сеансами браузера, управление профилями и встроенную интеграцию с Laravel Sanctum для аутентификации токена API.

Службы API-аутентификации Laravel

Laravel предлагает два дополнительных пакета, которые помогут вам в управлении токенами API и аутентификации запросов, сделанных с помощью токенов API: Passport и Sanctum. Обратите внимание, что эти библиотеки и встроенные в Laravel библиотеки аутентификации на основе файлов cookie не являются взаимоисключающими. Эти библиотеки в основном ориентированы на аутентификацию токена API, в то время как встроенные службы аутентификации ориентированы на web-аутентификацию на основе файлов cookie. Многие приложения будут использовать как встроенные службы аутентификации Laravel на основе файлов cookie, так и один из пакетов API-аутентификации Laravel.

Passport

Passport – это провайдер аутентификации OAuth2, предлагающий различные OAuth2 Grant Types («способы запросы»), которые позволяют вам выдавать различные типы токенов. В общем, это надежный и сложный пакет для аутентификации API. Однако большинству приложений не требуются сложный функционал, предлагаемый спецификацией OAuth2, что может сбивать с толку как пользователей, так и разработчиков. Кроме того, разработчики исторически не понимали, как аутентифицировать приложения SPA или мобильные приложения с помощью провайдеров аутентификации OAuth2, таких, как Passport.

Sanctum

В ответ на сложность OAuth2 и путаницу разработчиков мы решили создать более простой и оптимизированный пакет аутентификации, который мог бы обрабатывать как сторонние веб-запросы из браузера, так и запросы API через токены. Эта цель была реализована с выпуском Laravel Sanctum, который следует считать предпочтительным и рекомендуемым пакетом аутентификации для приложений, и который будет предлагать собственный веб-интерфейс в дополнение к API, или работать с одностраничным приложением (SPA), которое существует отдельно от серверного приложения Laravel, или приложений, предлагающих мобильный клиент.

Laravel Sanctum – это гибридный пакет аутентификации через Web / API, который может управлять всем процессом аутентификации вашего приложения. Это возможно, потому что когда приложения на основе Sanctum получают запрос, Sanctum сначала определяет, содержит ли запрос файл cookie сессии, который ссылается на аутентифицированную сессию. Sanctum выполняет это, вызывая встроенные службы аутентификации Laravel, которые мы обсуждали ранее. Если запрос не аутентифицируется с помощью файла cookie сессии, то Sanctum проверит запрос на наличие токена API. Если присутствует токен API, то Sanctum аутентифицирует запрос с помощью этого токена. Чтобы узнать больше об этом процессе, обратитесь к разделу «Как это работает» документации Sanctum.

Laravel Sanctum – это пакет API, который мы выбрали для включения в стартовый комплект Laravel Jetstream, потому что мы считаем, что он лучше всего подходит для большинства веб-приложений, требующих аутентификации.

Предварительный итог и выбор вашего стека

Таким образом, если ваше приложение будет доступно через браузер, и вы создаете монолитное приложение Laravel, то ваше приложение будет использовать встроенные службы аутентификации Laravel.

Затем, если ваше приложение предлагает API, который будут использовать третьи стороны, то вы можете выбрать между Passport или Sanctum, чтобы обеспечить аутентификацию токена API для вашего приложения. В целом, по возможности следует отдавать предпочтение Sanctum, поскольку это простое и полное решение для аутентификации API, аутентификации SPA и мобильной аутентификации, включая поддержку «scopes» или «abilities».

Если вы создаете одностраничное приложение (SPA), которое будет работать с серверной частью Laravel, то вам следует использовать Laravel Sanctum. При использовании Sanctum вам потребуется либо самостоятельно реализовать свои собственные маршруты аутентификации на сервере, либо использовать Laravel Fortify как серверную службу аутентификации, которая предлагает маршруты и контроллеры для такого функционала, как регистрация, сброс пароля, подтверждение электронной почты и многое другое.

Passport можно выбрать, если вашему приложению необходим абсолютно весь функционал, предоставляемый спецификацией OAuth2.

И, если вы хотите быстро начать работу, то мы рады порекомендовать пакет Laravel Jetstream как быстрый способ запустить новое приложение Laravel, который уже использует предпочтительный стек аутентификации: встроенные службы аутентификации Laravel и Laravel Sanctum.

Быстрый запуск аутентификации

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

Установка стартовых комплектов

Во-первых, вы должны установить стартовый комплект Laravel. Наши текущие стартовые комплекты, Laravel Breeze и Laravel Jetstream, предлагают красиво оформленные отправные точки для интеграции аутентификации в ваше новое приложение Laravel.

Laravel Breeze – это минимальная и простая реализация всех возможностей аутентификации Laravel, включая вход в систему, регистрацию, сброс пароля, подтверждение электронной почты и подтверждение пароля. Слой представления Laravel Breeze состоит из простых шаблонов Blade, стилизованных с помощью Tailwind CSS.

Laravel Jetstream – это более надежный стартовый комплект для приложений, который включает поддержку построения вашего приложения с помощью Livewire или Inertia.js и Vue. Кроме того, Jetstream предлагает дополнительную поддержку двухфакторной аутентификации, команд, управления профилями, управления сеансами браузера, поддержки API через Laravel Sanctum, удаления аккаунтов и т. д.

Получение аутентифицированного пользователя

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

use Illuminate\Support\Facades\Auth;


$user = Auth::user();


$id = Auth::id();

В качестве альтернативы, как только пользователь аутентифицирован, вы можете получить доступ к аутентифицированному пользователю через экземпляр Illuminate\Http\Request. Помните, что объявленные типы зависимостей в методах вашего контроллера будут автоматически внедрены. Объявив объект Illuminate\Http\Request, вы можете получить доступ к аутентифицированному пользователю из любого метода контроллера вашего приложения с помощью метода user запроса:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class FlightController extends Controller
{
    
    public function update(Request $request)
    {
        
    }
}

Определение статуса аутентификации пользователя

Чтобы определить, аутентифицирован ли пользователь, выполняющий входящий HTTP-запрос, вы можете использовать метод check фасада Auth. Этот метод вернет true, если пользователь аутентифицирован:

use Illuminate\Support\Facades\Auth;

if (Auth::check()) {
    
}
Несмотря на то, что можно определить, аутентифицирован ли пользователь с помощью метода check, вы обычно будете использовать посредника для проверки статуса аутентификации пользователя перед предоставлением пользователю доступа к определенным маршрутам / контроллерам. Чтобы узнать больше об этом, ознакомьтесь с документацией по защите маршрутов.

Защита маршрутов

Посредник маршрута используется для того, чтобы разрешить только аутентифицированным пользователям доступ к указанному маршруту. Laravel содержит посредник auth, который ссылается на класс Illuminate\Auth\Middleware\Authenticate. Поскольку этот посредник уже зарегистрирован в HTTP-ядре вашего приложения, все, что вам нужно сделать, это задать посредника к определению маршрута:

Route::get('/flights', function () {
    
})->middleware('auth');

Перенаправление неаутентифицированных пользователей

Когда посредник auth обнаруживает неаутентифицированного пользователя, он перенаправляет пользователя на именованный маршрут login. Вы можете изменить это поведение, обновив функцию redirectTo в файле app/Http/Middleware/Authenticate.php вашего приложения:


protected function redirectTo($request)
{
    return route('login');
}

Указание охранника аутентификации

При задании посредника auth маршруту вы также можете указать, какой «охранник» должен использоваться для аутентификации пользователя. Указанный охранник должен соответствовать одному из указанных в массиве guards конфигурационного файла config/auth.php:

Route::get('/flights', function () {
    
})->middleware('auth:admin');

Частота попыток входа в приложение

Если вы используете стартовые комплекты Laravel Breeze или Laravel Jetstream, то к попыткам входа в систему будет автоматически применяться ограничение. По умолчанию, если пользователь не сможет предоставить правильные учетные данные после нескольких попыток, то он не сможет войти в систему в течение одной минуты. Частота попыток уникальна для имени пользователя / адреса электронной почты и в совокупности с IP-адресом.

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

Самостоятельная реализация аутентификации пользователей

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

Мы получим доступ к службам аутентификации Laravel через фасад Auth, поэтому нам нужно обязательно импортировать фасад Auth в верхней части нашего класса. Далее, давайте проверим метод attempt. Метод attempt обычно используется для обработки попыток аутентификации из формы входа в систему вашего приложения. Если аутентификация прошла успешно, то вы должны повторно создать сессию пользователя, чтобы предотвратить фиксацию сессии:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    
    public function authenticate(Request $request)
    {
        $credentials = $request->only('email', 'password');

        if (Auth::attempt($credentials)) {
            $request->session()->regenerate();

            return redirect()->intended('dashboard');
        }

        return back()->withErrors([
            'email' => 'The provided credentials do not match our records.',
        ]);
    }
}

Метод attempt принимает массив пар ключ / значение в качестве своего первого аргумента. Значения в массиве будут использоваться для поиска пользователя в таблице базы данных. Итак, в приведенном выше примере пользователь будет извлечен по значению столбца email. Если пользователь найден, то хешированный пароль, хранящийся в базе данных, будет сравниваться со значением password, переданным в метод через массив. Вы не должны хешировать значение пароля входящего запроса, поскольку фреймворк автоматически хеширует это значение, прежде чем сравнивать его с хешированным паролем в базе данных. Если два хешированных пароля совпадают, то для пользователя будет запущена аутентифицированная сессия.

Помните, что службы аутентификации Laravel будут получать пользователей из вашей базы данных на основе конфигурации провайдера вашего охранника аутентификации. В конфигурационном файле config/auth.php по умолчанию указан провайдер пользователей Eloquent, и ему дано указание использовать модель App\Models\User при получении пользователей. Вы можете изменить эти значения в своем файле конфигурации в зависимости от потребностей вашего приложения.

Метод attempt вернет true, если аутентификация прошла успешно. В противном случае будет возвращено false.

Метод intended экземпляра Illuminate\Routing\Redirector Laravel, будет перенаправлять пользователя на URL-адрес, к которому он пытался получить доступ, прежде чем он будет перехвачен посредником аутентификации. Этому методу может быть предоставлен резервный URI, в случае, если методу intended переданный адрес недоступен.

Указание дополнительных условий

При желании вы также можете добавить дополнительные условия запроса к запросу аутентификации в дополнение к электронной почте и паролю пользователя. Для этого мы можем просто добавить условия запроса в массив, переданному методу attempt. Например, мы можем проверить, что пользователь отмечен как «активный»:

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    
}
В этих примерах email не является обязательным параметром, он просто используется в качестве примера. Вы должны использовать любое имя столбца, равнозначное «имени пользователя» в таблице базы данных.

Доступ к конкретному экземпляру охранника аутентификации

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

Имя охранника, переданное методу guard, должно соответствовать одному из настроенных в вашем файле конфигурации auth.php охраннику:

if (Auth::guard('admin')->attempt($credentials)) {
    
}

Запоминание пользователей

Многие веб-приложения содержат флажок «Запомнить меня» в форме входа. Если вы хотите реализовать функционал «Запомнить меня» в своем приложении, то вы можете передать логическое значение в качестве второго аргумента метода attempt.

Когда это значение равно true, Laravel будет поддерживать аутентификацию пользователя неопределенно долго или до тех пор, пока он не выйдет из системы вручную. Ваша таблица users должна включать столбец remember_token, который будет использоваться для хранения токена функционала «Запомнить меня». Миграция таблицы пользователей, входящая в новые приложения Laravel, уже содержит этот столбец:

use Illuminate\Support\Facades\Auth;

if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
    
}

Другие методы аутентификации

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

Если вам нужно задать экземпляр существующего пользователя в качестве текущего аутентифицированного, то вы можете передать этот экземпляр методу login фасада Auth. Переданный экземпляр пользователя должен быть реализацией контракта Illuminate\Contracts\Auth\Authenticatable. Модель App\Models\User, поставляемая с Laravel, уже реализует этот интерфейс. Этот метод аутентификации полезен, когда у вас уже есть экземпляр пользователя, например, сразу после того, как пользователь регистрируется в вашем приложении:

use Illuminate\Support\Facades\Auth;

Auth::login($user);

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

Auth::login($user, $remember = true);

При необходимости вы можете указать охранника аутентификации перед вызовом метода login:

Auth::guard('admin')->login($user);

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

Для аутентификации пользователя с использованием первичного ключа записи в базе данных вы можете использовать метод loginUsingId. Этот метод принимает первичный ключ пользователя, которого вы хотите аутентифицировать:

Auth::loginUsingId(1);

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

Auth::loginUsingId(1, $remember = true);

Аутентификация пользователя для текущего запроса

Вы можете использовать метод once для аутентификации пользователя в приложении только для одного запроса. При вызове этого метода не будут использоваться сессии или файлы cookie:

if (Auth::once($credentials)) {
    
}

Basic HTTP-аутентификация

Basic HTTP-аутентификация обеспечивает быстрый способ аутентификации пользователей вашего приложения без создания специальной «страницы входа». Для начала задайте маршруту посредника auth.basic. Посредник auth.basic поставляется с Laravel, поэтому вам не нужно его определять:

Route::get('/profile', function () {
    
})->middleware('auth.basic');

После того как посредник задан маршруту, вам будет автоматически предложено ввести учетные данные при доступе к маршруту в вашем браузере. По умолчанию посредник auth.basic предполагает, что столбец email в вашей таблице базы данных users является его «логином».

Примечание о FastCGI

Если вы используете PHP FastCGI и Apache для своего приложения Laravel, то аутентификация HTTP Basic может работать некорректно. Чтобы исправить эти проблемы, в файл .htaccess вашего приложения можно добавить следующие строки:

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Basic HTTP-аутентификация без сохранения состояния

Вы также можете использовать Basic HTTP-аутентификацию без задания cookie идентификатора пользователя в сессии. Это в первую очередь полезно, если вы решите использовать HTTP-аутентификацию для аутентификации запросов к API вашего приложения. Для этого определите посредника, который вызывает метод onceBasic. Если метод onceBasic не возвращает ответа, то запрос может быть передан дальше в приложение:

namespace App\Http\Middleware;

use Illuminate\Support\Facades\Auth;

class AuthenticateOnceWithBasicAuth
{
    
    public function handle($request, $next)
    {
        return Auth::onceBasic() ?: $next($request);
    }

}

Затем зарегистрируйте посредника и задайте его маршруту:

Route::get('/api/user', function () {
    
})->middleware('auth.basic.once');

Выход из приложения

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

В дополнение к вызову метода logout рекомендуется аннулировать сессию пользователя и повторно сгенерировать его токен CSRF. После выхода пользователя из системы вы обычно перенаправляете пользователя в корень вашего приложения:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;


public function logout(Request $request)
{
    Auth::logout();

    $request->session()->invalidate();

    $request->session()->regenerateToken();

    return redirect('/');
}

Аннулирование сессий на других устройствах

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

Перед тем как начать, вы должны убедиться, что посредник Illuminate\Session\Middleware\AuthenticateSession присутствует и не закомментирован в вашей группе посредников web класса App\Http\Kernel:

'web' => [
    
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    
],

Затем вы можете использовать метод logoutOtherDevices фасада Auth. Этот метод требует, чтобы пользователь подтвердил свой текущий пароль, который ваше приложение должно принять через форму ввода:

use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($currentPassword);

Когда вызывается метод logoutOtherDevices, другие сессии пользователя будут полностью аннулированы, то есть он будут «отключен» от всех охранников, которым он ранее был аутентифицированы.

Подтверждение пароля

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

В следующей документации обсуждается, как напрямую интегрироваться с функционалом подтверждения пароля Laravel; однако, если вы хотите начать работу быстрее, то стартовые комплекты Laravel уже включают поддержку этого функционала!

Конфигурация подтверждения пароля

После подтверждения пароля пользователю не будет предлагаться повторно подтвердить пароль в течение трех часов. Однако вы можете настроить время, по истечении которого пользователю будет предложено повторно ввести пароль, изменив значение параметра конфигурации password_timeout в файле конфигурации config/auth.php вашего приложения.

Маршрутизация подтверждения пароля

Форма подтверждения пароля

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

Route::get('/confirm-password', function () {
    return view('auth.confirm-password');
})->middleware('auth')->name('password.confirm');

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

Процесс подтверждения пароля

Затем мы определим маршрут, который будет обрабатывать запрос формы из шаблона «подтвердить пароль». Этот маршрут будет отвечать за проверку пароля и перенаправление пользователя к месту назначения:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redirect;

Route::post('/confirm-password', function (Request $request) {
    if (! Hash::check($request->password, $request->user()->password)) {
        return back()->withErrors([
            'password' => ['The provided password does not match our records.']
        ]);
    }

    $request->session()->passwordConfirmed();

    return redirect()->intended();
})->middleware(['auth', 'throttle:6,1'])->name('password.confirm');

Прежде чем двигаться дальше, давайте рассмотрим этот маршрут более подробно. Во-первых, определяется, что поле password запроса действительно соответствует паролю аутентифицированного пользователя. Если пароль действителен, то нам нужно сообщить сессии Laravel, что пользователь подтвердил свой пароль. Метод passwordConfirmed устанавливает временную метку в сессии пользователя, которую Laravel может использовать, чтобы определить, когда пользователь последний раз подтвердил свой пароль. Наконец, мы можем перенаправить пользователя по назначению.

Защита маршрутов

Вы должны убедиться, что любому маршруту, связанному с подтверждением пароля, назначен посредник password.confirm. Этот посредник входит в стандартную установку Laravel и автоматически сохраняет предполагаемое место назначения пользователя в сессии, чтобы пользователя можно было перенаправить в это место после подтверждения своего пароля. После сохранения предполагаемого пункта назначения пользователя в сессии посредник перенаправит пользователя на именованный маршрут password.confirm:

Route::get('/settings', function () {
    
})->middleware(['password.confirm']);

Route::post('/settings', function () {
    
})->middleware(['password.confirm']);

Добавление своих охранников аутентификации

Вы можете определить своих собственных охранников аутентификации, используя метод extend фасада Auth. Вы должны разместить свой вызов метода extend внутри поставщика служб. Поскольку Laravel уже содержит AuthServiceProvider, мы можем разместить код в этом поставщике:

namespace App\Providers;

use App\Services\Auth\JwtGuard;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
    
    public function boot()
    {
        $this->registerPolicies();

        Auth::extend('jwt', function ($app, $name, array $config) {
            

            return new JwtGuard(Auth::createUserProvider($config['provider']));
        });
    }
}

Как вы можете видеть в приведенном выше примере, замыкание, переданное методу extend, должно возвращать реализацию Illuminate\Contracts\Auth\Guard. Этот интерфейс содержит несколько методов, которые вам необходимо реализовать для определения своего охранника. После того как ваш охранник был определен, вы можете ссылаться на него в конфигурации guards конфигурационного файла config/auth.php:

'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

Анонимные охранники аутентификации на базе HTTP-запросов

Самый простой способ реализовать собственную систему аутентификации на базе HTTP-запросов – использовать метод Auth::viaRequest. Этот метод позволяет быстро определить процесс аутентификации с помощью одного замыкания.

Для начала вызовите метод Auth::viaRequest в методе boot вашего AuthServiceProvider. Метод viaRequest принимает имя драйвера аутентификации в качестве своего первого аргумента. Это имя может быть любой строкой, описывающей вашего охранника. Второй аргумент, передаваемый методу, должно быть замыкание, которое принимает входящий HTTP-запрос и возвращает экземпляр пользователя или, если аутентификация не удалась, то null:

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;


public function boot()
{
    $this->registerPolicies();

    Auth::viaRequest('custom-token', function (Request $request) {
        return User::where('token', $request->token)->first();
    });
}

После того как ваш драйвер аутентификации был определен, вы можете настроить его как драйвер в конфигурации guards конфигурационного файла config/auth.php:

'guards' => [
    'api' => [
        'driver' => 'custom-token',
    ],
],

Добавление своих провайдеров пользователей

Если вы не используете традиционную реляционную базу данных для хранения своих пользователей, то вам нужно будет расширить Laravel своим собственным провайдером аутентификации пользователей. Мы будем использовать метод provider фасада Auth для определения собственного провайдера пользователей. Провайдер пользователей должен вернуть реализацию Illuminate\Contracts\Auth\UserProvider:

namespace App\Providers;

use App\Extensions\MongoUserProvider;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;

class AuthServiceProvider extends ServiceProvider
{
    
    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('mongo', function ($app, array $config) {
            

            return new MongoUserProvider($app->make('mongo.connection'));
        });
    }
}

После того как вы зарегистрировали провайдера с помощью метода provider, вы можете переключиться на нового провайдера пользователей в конфигурационном файле config/auth.php. Сначала определите провайдера, который использует ваш новый драйвер:

'providers' => [
    'users' => [
        'driver' => 'mongo',
    ],
],

Наконец, вы можете указать этого провайдера в своей конфигурации guards:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
],

Контракт UserProvider

Реализации Illuminate\Contracts\Auth\UserProvider отвечают за получение реализации Illuminate\Contracts\Auth\Authenticatable из системы постоянного хранения, такой как MySQL, MongoDB и т. д. Эти два интерфейса позволяют механизмам аутентификации Laravel продолжать функционировать независимо от того, как хранятся пользовательские данные или какой тип класса используется для представления аутентифицированного пользователя.

Давайте посмотрим на контракт Illuminate\Contracts\Auth\UserProvider:

namespace Illuminate\Contracts\Auth;

interface UserProvider
{
    public function retrieveById($identifier);
    public function retrieveByToken($identifier, $token);
    public function updateRememberToken(Authenticatable $user, $token);
    public function retrieveByCredentials(array $credentials);
    public function validateCredentials(Authenticatable $user, array $credentials);
}
  • Метод retrieveById обычно принимает ключ, представляющий пользователя, такой как автоинкрементный идентификатор из базы данных MySQL. Реализация Authenticatable, соответствующая идентификатору, должна быть получена и возвращена методом.

  • Метод retrieveByToken извлекает пользователя по его уникальному идентификатору $identifier и $token, обычно хранящимся в столбце remember_token базы данных. Как и в предыдущем методе, этот метод должен вернуть реализацию Authenticatable соответствующую значению токена.

  • Метод updateRememberToken обновляет remember_token экземпляра $user новым $token. Новый токен назначается пользователям при успешной попытке аутентификации с отмеченным флажком «Запомнить меня» или когда пользователь выходит из системы.

  • Метод retrieveByCredentials принимает массив учетных данных, переданный методу Auth::attempt при попытке аутентификации в приложении. Затем метод должен «запросить» у постоянного хранилища пользователя, соответствующего этим учетным данным. Как правило, этот метод запускает запрос с условием WHERE, который ищет запись пользователя с «именем пользователя», равнозначным $credentials['имя пользователя']. Метод должен возвращать реализацию Authenticatable. Этот метод не должен пытаться выполнить проверку пароля или аутентификацию.

  • Метод validateCredentials должен сравнивать переданный $user с $credentials для аутентификации пользователя. Например, этот метод обычно использует метод Hash::check для сравнения значения $user->getAuthPassword() со значением $credentials['password']. Этот метод должен возвращать true или false, указывая, действителен ли пароль.

Контракт Authenticatable

Теперь, когда мы изучили каждый из методов UserProvider, давайте взглянем на контракт Authenticatable. Помните, что провайдеры пользователей должны возвращать реализации этого интерфейса из методов retrieveById, retrieveByToken, и retrieveByCredentials:

namespace Illuminate\Contracts\Auth;

interface Authenticatable
{
    public function getAuthIdentifierName();
    public function getAuthIdentifier();
    public function getAuthPassword();
    public function getRememberToken();
    public function setRememberToken($value);
    public function getRememberTokenName();
}

Этот интерфейс прост. Метод getAuthIdentifierName должен возвращать имя поля «первичного ключа» пользователя, а метод getAuthIdentifier должен возвращать «первичный ключ» пользователя. При использовании серверной части MySQL это, вероятно, будет автоинкрементный первичный ключ, присваиваемый записи пользователя. Метод getAuthPassword должен возвращать хешированный пароль пользователя.

Этот интерфейс позволяет системе аутентификации работать с любым классом User, независимо от того, какой ORM или уровень абстракции хранилища вы используете. По умолчанию Laravel включает класс App\Models\User в каталог app/Models, который реализует этот интерфейс.

BASIC авторизация

Данный вид авторизации чаще всего используется браузером для доступа к функциям API.

При использовании данного метода необходимо в заголовке каждого запроса указывать:

Authorization: Basic {login}:{password}

Допускается base64 при формировании строки {login}:{password}

Авторизация методом GET

Еще один способ авторизации - отправить GET запрос по адресу /api/v1/session, при этом в url запросе указать параметры login и password:

     https://localhost:9000/api/v1/session?username=${Username}&password=${Password}

Ответ сервера:

{
Access_token:"123123123", Token_type:"bearer", Expires_in:86400, Refresh_token:"321321321",
}

Авторизация методом POST

Авторизация по логину и паролю происходит путем отправки POST запроса на сервер, в результате которого возвращается access_token и refresh token в формате JSON.

Пример запроса:

POST /oauth/token HTTP/1.1
Host: mobilesmarts.ru/api/session
Content-Type: application/x-www-form-urlencoded

grant_type=password&client_id=123&client_secret=user&username=user@domain.ru&password=123456

Ответ сервера:

{
Access_token:"123123123",
Token_type:"bearer", Expires_in:86400, Refresh_token:"321321321", }

Восстановление после окончания срока действия сессии

Восстановление после окончания срока действия сессии происходит путем отправки refresh_token на сервер, в результате приходит новый access_token и refresh_token

Пример:

POST /oauth/token HTTP/1.1
Host: mobilesmarts.ru/api/session
Content-Type: application/x-www-form-urlencoded

grant_type:refresh_token&client_id=123&client_secret=user&refresh_token=321321321

Ответ:

HTTP/1.1 200 OK
Content-Type: application/json

{
Access_token:"99999",
Token_type:"bearer",
Expires_in:86400,
Refresh_token:"789789789",
}

Зачем использовать встроенную проверку подлинности?

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

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

  • Служба приложений Azure позволяет интегрировать различные возможности проверки подлинности с веб-приложением или API, лишая вас необходимости реализовывать их самостоятельно.
  • Она встроена непосредственно в платформу и для использования не требует какого бы то ни было опыта работы с конкретным языком, пакетом SDK или средством обеспечения безопасности или даже какого-либо кода.
  • Можно выполнить интеграцию с несколькими поставщиками входа. Например, Azure AD, Facebook, Google, Twitter.

Поставщики удостоверений

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

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

Рекомендации по использованию встроенной проверки подлинности

Включение этой функции приведет к автоматическому перенаправлению всех запросов к приложению по протоколу HTTPS независимо от параметра конфигурации Службы приложений для принудительного применения HTTPS. Это можно отключить с помощью параметра  requireHttps в конфигурации V2. Однако мы рекомендуем использовать протокол HTTPS, и вы должны позаботиться о том, чтобы маркеры безопасности не передавались через небезопасные соединения HTTP.

Службу приложений можно использовать для проверки подлинности с ограничением или без ограничения доступа к содержимому и API сайта. Чтобы предоставить доступ к приложению только пользователям, прошедшим проверку подлинности, для параметра Предпринимаемое действие, если проверка подлинности для запроса не выполнена установите вход с помощью одного из настроенных поставщиков удостоверений. Чтобы выполнять проверку подлинности, но не ограничивать доступ, для параметра Предпринимаемое действие, если проверка подлинности для запроса не выполнена установите "Разрешить анонимные запросы (нет действия)".

Примечание

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

Принцип работы

Архитектура функций в Windows (без развертывания контейнера)

Архитектура функций в Linux и контейнерах

Поток аутентификации

Поведение авторизации

Утверждения пользователей и приложений

Хранилище токенов

Ведение журнала и трассировка

Архитектура функций в Windows (без развертывания контейнера)

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

Схема архитектуры с запросами, перехваченными процессом в песочнице сайта, который взаимодействует с поставщиками удостоверений до разрешения трафика в развернутый сайт

Этот модуль выполняет следующие операции для вашего приложения:

  • проверку подлинности пользователей с указанным поставщиком;
  • проверку, хранение и обновление токенов;
  • управление сеансом с проверкой подлинности;
  • вставка сведений об удостоверении в заголовки запросов.

Модуль работает отдельно от кода приложения и настраивается с помощью параметров приложения. Для кода приложения не нужны пакеты SDK, определенные языки или изменения.

Архитектура функций в Linux и контейнерах

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

Поток проверки подлинности

Поток проверки подлинности одинаков для всех поставщиков, но будет различным для разных способов входа в систему: с использованием пакета SDK поставщика или без.

  • Без использования пакета SDK поставщика. Приложение делегирует федеративный вход в службу приложений. Обычно это относится к приложениям браузера, которые могут предоставить пользователю страницу входа поставщика. Код сервера управляет процессом входа, поэтому он также называется управляемым сервером потоком или потоком сервера. Этот вариант применяется к браузерным приложениям. Он также относится к собственным приложениям, в которых вход пользователей в систему выполняется с помощью пакета SDK для клиента мобильных приложений. Пакет SDK открывает веб-представление, в котором пользователи выполняют вход с помощью проверки подлинности службы приложений.
  • С использованием пакета SDK поставщика. Вход пользователей в приложение на странице поставщика выполняется вручную, а затем приложение отправляет маркер проверки подлинности в Службу приложений Azure для проверки. Обычно это относится к внебраузерным приложениям, которые не могут предоставить пользователю страницу входа в систему. Код приложения управляет процессом входа, поэтому его также называют управляемым клиентом потоком или потоком клиента. Этот вариант применяется к REST API, Функциям Azure и клиентам браузера JavaScript, а также к браузерным приложениям, которым требуется больше гибкости при входе в систему. Это также относится к собственным мобильным приложениям, в которых вход пользователей в систему выполняется с помощью пакета SDK поставщика.

Вызовы из доверенного приложения браузера в Службе приложений к другому REST API в Службе приложений или Функциях Azure могут проходить проверку подлинности с помощью управляемого сервером потока. Дополнительные сведения см. в статье Настройка проверки подлинности и авторизации в Службе приложений Azure.

В приведенной ниже таблице показаны шаги выполнения потока проверки подлинности.

Шаг Без использования пакета SDK поставщика С использованием пакета SDK поставщика
1. Вход пользователя Перенаправляет клиента к /.auth/login/. Код клиента выполняет вход пользователя непосредственно через пакет SDK поставщика и получает токен проверки подлинности. Дополнительные сведения см. в документации поставщика.
2. Действия после проверки подлинности Поставщик перенаправляет клиент к /.auth/login//callback. Код клиента отправляет маркер от поставщика в /.auth/login/ для проверки.
3. Установка проверенного сеанса Служба приложений добавляет файлы cookie, прошедшие проверку подлинности, в ответ. Служба приложений возвращает собственный токен проверки подлинности в код клиента.
4. Обработка содержимого, прошедшего проверку подлинности Клиент включает файлы cookie, прошедшие проверку подлинности, в последующие запросы (автоматически обрабатываются браузером). Код клиента предоставляет токен проверки подлинности в заголовке X-ZUMO-AUTH (автоматически обрабатывается пакетами SDK для клиента мобильных приложений).

Для клиентских браузеров служба приложений может автоматически перенаправлять всех не прошедших проверку пользователей к /.auth/login/. Вы также можете отправить пользователям одну или несколько ссылок /.auth/login/, чтобы они вошли в ваше приложение с использованием поставщика по выбору.

Поведение авторизации

На портале Azure можно настроить Службу приложений, используя несколько вариантов поведения в случае, если поступающий запрос не прошел проверку подлинности. Ниже описаны возможные варианты.

Разрешить запросы, не прошедшие проверку подлинности

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

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

Требовать проверку подлинности

Этот параметр отклоняет направляющийся в приложение трафик, не прошедший проверку подлинности. Такое отклонение может заключаться в перенаправлении в один из настроенных поставщиков удостоверений. В таких случаях клиент браузера перенаправляется в /.auth/login/ для выбранного поставщика. Если анонимный запрос поступает из собственного мобильного приложения, возвращаемый ответ HTTP 401 Unauthorized. Можно также настроить отклонение на возврат ответа HTTP 401 Unauthorized или HTTP 403 Forbidden для всех запросов.

В этом случае в клиентском приложении не нужен код для проверки подлинности. Более точная авторизация, например авторизация для конкретной роли, может выполняться путем проверки утверждений пользователя (см. раздел Access user claims (Доступ к утверждениям пользователя)).

Внимание!

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

Примечание

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

Утверждения пользователей и приложений

Для всех языковых платформ Служба приложений делает утверждения во входящем токене (поступающем от пользователя, прошедшего проверку подлинности, или клиентского приложения) доступными для вашего кода путем их вставки в заголовки запроса. Для приложений ASP.NET 4.6 служба приложений заполняет свойство ClaimsPrincipal.Current утверждениями пользователя, прошедшими проверку подлинности, поэтому вы можете следовать стандартным шаблонам кода .NET, включая атрибут [Authorize]. Аналогичным образом для приложений PHP служба приложений заполняет переменную _SERVER['REMOTE_USER']. Для приложений Java утверждения доступны из сервлета Tomcat.

Для Функций Azure ClaimsPrincipal.Current не заполняется для кода .NET, но вы по-прежнему можете найти утверждения пользователя в заголовках запроса или получить объект ClaimsPrincipal из контекста запроса или даже через параметр привязки. Дополнительные сведения см. в разделе Работа с удостоверениями клиентов.

Дополнительные сведения см. в разделе Access user claims (Доступ к утверждениям пользователя).

При работе с .NET Core Microsoft.Identity.Web поддерживает заполнение текущего пользователя с использованием функции проверки подлинности и авторизации. Дополнительные сведения см. на вики-сайте Microsoft.Identity.Web или в руководстве по веб-приложению, которое обращается к Microsoft Graph.

Хранилище токенов

Служба приложений предоставляет встроенное хранилище токенов, которое представляет собой репозиторий токенов, связанных с пользователями ваших веб-приложений, API или собственных мобильных приложений. При включении проверки подлинности с помощью любого поставщика это хранилище токенов немедленно становится доступным для вашего приложения. Если для кода вашего приложения требуется доступ к данным из этих поставщиков от имени пользователя, чтобы:

  • опубликовать запись в ленте Facebook прошедшего проверку подлинности пользователя;
  • считать корпоративные данные пользователя с помощью API Microsoft Graph;

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

Токены идентификатора, доступа и обновления кэшируются для проверенного сеанса. Они доступны только соответствующему пользователю.

Если вам не нужно использовать токены в приложении, можно отключить хранилище токенов на странице Проверка подлинности и авторизация приложения.

Ведение журнала и трассировка

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

Предопределённые PHP переменные

php.net

  • PHP_AUTH_USER
  • PHP_AUTH_PW
  • AUTH_TYPE

Basic HTTP Authentication

Чтобы создать проверку пользователя во всплывающем окне достаточно следующего кода:

// www.andreyolegovich.ru lesson $username = 'urn.su'; $password = 'heihei.ru'; if (!isset($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="Andrei"'); }

Тем не менее, желательно добавить немного функционала:

$username = 'urn.su'; $password = 'heihei.ru'; if (!isset($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="Andrei"'); header('HTTP/1.0 401 Unauthorized'); echo 'Введите логин и пароль, чтобы получить доступ к странице'; exit; } else { echo "

Привет {$_SERVER['PHP_AUTH_USER']}.

"; echo "

Вы ввели пароль {$_SERVER['PHP_AUTH_PW']} .

";
} if ($_SERVER['PHP_AUTH_USER'] !== $username || $_SERVER['PHP_AUTH_PW'] !== $password ) { header('HTTP/1.0 401 Unauthorized'); echo 'Имя пользователя или пароль введены неверно\n'; exit; }

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

В Firefox это Library → History → Clear Recent History → Active Logins

В Chrome это Passwords and other sing-in data (в Clear browsing data → Advanced)

В Safari это Clear History

Если пароль поменялся, пользователя со старым паролем не выкинет и т.д.

Примечание о совместимости

Пожалуйста, будьте осторожны при кодировании строк заголовка HTTP.

Чтобы гарантировать максимальную совместимость со всеми клиентами, ключевое слово "Basic" должно быть написано с прописной буквой "B", строка realm должна быть заключена в двойные (а не одинарные) кавычки, и ровно один пробел должен предшествовать коду 401 в строке заголовка HTTP/1.0 401. Параметры аутентификации должны быть разделены запятыми, как показано в приведенном выше примере дайджеста.

Очистить глобальные переменные

Очистить значения переменных $_SERVER['PHP_AUTH_USER'] и $_SERVER['PHP_AUTH_PW'] можно с помощью функции unset()

unset($_SERVER['PHP_AUTH_USER']); unset($_SERVER['PHP_AUTH_PW']);

HTTP Digest Authentication

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

Аналогичный метод используется в рамках VoIP-протокола SIP для аутентификации сервером обращения со стороны клиента, т.е. оконечного терминала.

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

Технически, аутентификация по дайджесту представляет собой применение криптографической хеш-функции MD5 к секрету пользователя с использованием случайных значений для затруднения криптоанализа и предотвращения replay-атак. Работает на уровне протокола HTTP.

Это более продвинутый вариант HTTP Аутентификации.

RFC

Можно использовать следующие опции ( полный список в RFC )

domain - домен

Необязательный список URI (через пробел), которые защищены данным запросом на аутентификацию.

algorithm

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

opaque

base64 или HEX строка которую генерирует сервер. Клиент должен вернуть opaque неизменённым.

nonce должен быть в одинарных кавычках (не в двойных)

nonce-count - HEX число, содержащее количество запросов, которые клиент отправил с nonce в запросе.

stale

От английского stale - устаревший.

Флаг, который показывает на то, что предыдущий запрос от клиента был отклонён из за того, что значение nonce было несвежим.

Сервер должен ставить флаг stale в TRUE (регистронечувствительный) если пароль и имя пользователя верные и только nonce устарел.

В этом случае клиент может попытаться отправить ещё один зашифрованный запрос не запрашивая у пользователя ввод пароля.

Если сервер отказал в соединении а stale поставлен в FALSE, либо любое значение кроме TRUE, либо вообще отсутствует, значит клиент должен запросить логин и пароль снова.

qop - Quality of Protection

Опция для HTTP Digest Authentication. Может принимать значения "auth" или "auth-int". Влияет на то как создается хэш.

Если поставить в "auth" будет использоваться только запрошенный URI. Если в "auth-int" то также будет использовано тело запроса.

rfc2617

cnonce - Уникальный id сгенерированный клиентом. Это число помогает клиенту и серверу подтвердить, что у них есть известный общий секрет. Необходимо когда сервер отправляет qop. Не должно посылаться если сервер не использовал qop директиву.

Как работает HTTP-аутентификация?

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

HTTP предлагает два протокола аутентификации:

  • Обычная проверка подлинности
  • Дайджест-проверка подлинности

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

Структура аутентификации запроса/ответа

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

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

Связанные с аутентификацией заголовки запросов/ответов

Сервер выдает запрос, используя заголовок ответа WWW-Authenticate. Он содержит информацию о протоколе и области безопасности.

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

Если учетные данные верны, сервер возвращает ответ и дополнительную информацию в необязательном заголовке ответа Authentication-Info.

Области безопасности

Области безопасности предоставляют способ связать разные права доступа к разным группам ресурсов на сервере. Они называются защитными пространствами.

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

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

/admin/statistics/financials.txt -> Realm = "Статистика администратора"

/images/img1.jpg -> Realm = «Изображения»

Когда вы пытаетесь получить доступ к financials.txt, сервер запрашивает у вас данные для авторизации, и ответ будет выглядеть следующим образом:

HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="Admin Statistics"

Пример простой HTTP-аутентификации

Теперь давайте объединим точки, рассмотрев простейший пример проверки подлинности по протоколу HTTP (обычная проверка подлинности, описанная ниже):

1. Пользовательский клиент -> Сервер

Пользователь запрашивает доступ к изображению на сервере.

GET /gallery/personal/images/image1.jpg HTTP/1.1
Host: www.somedomain.com
  1. Сервер -> Пользовательский клиент

Сервер отправляет пользователю запрос.

HTTP/1.1 401 Access Denied
WWW-Authenticate: Basic realm="gallery"
  1. Пользовательский клиент -> Сервер

Пользователь идентифицирует себя посредством ввода формы.

GET /gallery/personal/images/image1.jpg HTTP/1.1
Authorization: Basic Zm9vOmJhcg==
  1. Сервер -> Пользовательский клиент

Сервер проверяет учетные данные и отправляет статус 200 OK, код и данные изображения.

HTTP/1.1 200 OK
Content-type: image/jpeg
...

Не все так сложно, правда?

Теперь давайте перейдем к базовой аутентификации.

Базовая проверка подлинности (Basic)

Самый распространенный и поддерживаемый протокол. Он существует с HTTP/1.0, и каждый крупный клиент его реализует.

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

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

При обычной аутентификации имя пользователя и пароль объединяются в одну строку и разделяются двоеточием (:). После этого он кодирует их, используя кодировку Base64. Несмотря на то, как это выглядит, зашифрованная последовательность символов небезопасна, и вы можете легко ее декодировать.

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

GET /gallery/personal/images/image1.jpg HTTP/1.1
Authorization: Basic Zm9vOmJhcg==

«Zm9vOmJhcg ==» из этого примера - не что иное, как строка «foo: bar» в кодировке Base64.

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

Хуже того, кодирование имени пользователя и пароля не поможет. Третья злонамеренная сторона по-прежнему может отправить зашифрованную последовательность для достижения того же эффекта.

Также отсутствует защита от прокси или любого другого типа атак, которые изменяют тело запроса и оставляют заголовки запроса нетронутыми.

Итак, как видите, обычная аутентификация - это далеко не идеальный механизм аутентификации.

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

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

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

Дайджест-аутентификация (Digest)

Дайджест-аутентификация - более безопасная и надежная альтернатива простой, но небезопасной базовой аутентификации.

Итак, как это работает?

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

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

Пример Digest Authentication

1. Пользовательский клиент -> Сервер

GET /dir/index.html HTTP/1.0
Host: localhost

Клиент отправляет неаутентифицированный запрос.

2. Сервер -> Пользовательский клиент

HTTP/1.0 401 Unauthorized
WWW-Authenticate: Digest realm="shire@middleearth.com",
                        qop="auth,auth-int",
                        nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ",
                        opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw"
Content-Type: text/html
Content-Length: 153



  
    
Error

401 Unauthorized.

Сервер предлагает клиенту пройти аутентификацию с использованием дайджест-аутентификации и отправляет клиенту необходимую информацию.

3. Пользовательский клиент -> Сервер

GET /dir/index.html HTTP/1.0
Host: localhost
Authorization: Digest username="Gandalf",
                     realm="shire@middleearth.com",
                     nonce="cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ",
                     uri="/dir/index.html",
                     qop=auth,
                     nc=00000001,
                     cnonce="0a4f113b",
                     response="5a1c3bb349cf6986abf985257d968d86",
                     opaque="c29tZXJhbmRvbW9wYXF1ZXN0cmluZw"

Клиент вычисляет значение ответа и отправляет его вместе с именем пользователя, областью, URI, nonce, opaque, qop, nc и cnonce. Много всего.

Подробное объяснение

Давайте определим это:

  • nonce и opaque - определенные сервером строки, которые клиент возвращает после их получения.
  • qop (качество защиты) - одно или несколько предопределенных значений («auth» | «auth-int» | токен). Эти значения влияют на вычисление дайджеста.
  • cnonce - одноразовый номер клиента, должен генерироваться, если задано qop. Он используется, чтобы избежать атак на выбранный открытый текст и предоставить сообщению защиту целостности.
  • nc - счетчик одноразовых номеров, должен быть отправлен, если задано qop. Эта директива позволяет серверу обнаруживать повторы запросов, сохраняя свою собственную копию этого счетчика - если одно и то же значение nc появляется дважды, то запрос является повтором.

Атрибут ответа рассчитывается следующим образом:

HA1 = MD5("Gandalf:shire@middleearth.com:Lord Of The Rings")
       = 681028410e804a5b60f69e894701d4b4

HA2 = MD5("GET:/dir/index.html")
       = 39aff3a2bab6126f332b942af96d3366

Response = MD5( "681028410e804a5b60f69e894701d4b4:
                 cmFuZG9tbHlnZW5lcmF0ZWRub25jZQ:
                 00000001:0a4f113b:auth:
                 39aff3a2bab6126f332b942af96d3366" )
         = 5a1c3bb349cf6986abf985257d968d86

Если вам интересно узнать, как вычислить ответ в зависимости от qop, вы можете найти его в RFC 2617.

4. Сервер -> Пользовательский клиент

HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 2345
... 

Сервер вычисляет хэш самостоятельно и сравнивает их. Если они совпадают, он передает клиенту запрошенные данные.

Краткое резюме

Как видите, дайджест-аутентификацию сложнее понять и реализовать.

Она также более безопасна, чем обычная проверка подлинности, но все же уязвима для атаки "человек посередине". RFC 2617 рекомендует использовать вместо этого дайджест-аутентификацию базовой аутентификации, поскольку она устраняет некоторые ее недостатки. Это также не скрывает того факта, что дайджест-аутентификация по-прежнему является слабой по современным криптографическим стандартам. Ее надежность во многом зависит от реализации.

Итак, вкратце дайджест-аутентификация:

  • Не отправляет пароли в виде обычного текста по сети.
  • Предотвращает повторные атаки
  • Защита от подделки сообщений

Некоторые из слабых мест:

  • Уязвимость к атаке "человек посередине".
  • Многие параметры безопасности не требуются, и поэтому дайджест-проверка подлинности будет менее безопасной, если не задана.
  • Предотвращает использование надежных алгоритмов хеширования паролей при хранении паролей.

В связи с этим дайджест-аутентификация пока не получила широкого распространения. Базовая аутентификация намного проще и в сочетании с SSL еще более безопасна, чем дайджест-аутентификация.