Блог

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

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

Код слизан с библии и оформлен под мидлвар Laravel.

Первым делом создаем middleware app/Http/Middleware/HttpMiddleware.php:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class HttpMiddleware
{
	/**
	 * Handle an incoming request.
	 *
	 * @param    \Illuminate\Http\Request  $request
	 * @param    \Closure  $next
	 * @param    string|null  $guard
	 * @return    mixed
	 */
	public function handle(Request $request, Closure $next, $guard = null)
	{
		if(is_null($request->server('PHP_AUTH_DIGEST')))
		{
			return response()->make('Access denied.', 401, ['WWW-Authenticate' => 'Digest realm="Auth",qop="auth",nonce="'.uniqid().'",opaque="'.md5('Auth').'"']);
	    }

	    $users = config('auth.http_users');

		if(!($data = $this->digestParse($request->server('PHP_AUTH_DIGEST'))) || !isset($users[$data['username']]))
		{
			return response('Access denied.', 401);
		}

		$A1 = md5($data['username'].':Auth:'.$users[$data['username']]);
		$A2 = md5($request->server('REQUEST_METHOD').':'.$data['uri']);
		$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

		if($data['response'] != $valid_response)
		{
			return response('Access denied.', 401);
		}

		return $next($request);
	}

	/**
	 * @param    string $txt
	 * @return    array|bool
	 */
	private function digestParse(string $txt)
	{
		$needed_parts = ['nonce' => 1, 'nc' => 1, 'cnonce' => 1, 'qop' => 1, 'username' => 1, 'uri' => 1, 'response' => 1];
		$data = [];
		$keys = implode('|', array_keys($needed_parts));

		preg_match_all('@('.$keys.')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

		foreach($matches as $m)
		{
			$data[$m[1]] = $m[3] ? $m[3] : $m[4];
			unset($needed_parts[$m[1]]);
		}

		return $needed_parts ? false : $data;
	}
}

Подключаем мидлвар в app/Http/Kernel.php:

protected $middlewareGroups = [
    // ...
    'http' => [
        \App\Http\Middleware\HttpMiddleware::class
    ]
];

Добавляем массив с пользователями в config/auth.php:

<?php

return [
    // ...
    'http_users' => [
        'login' => 'passord',
        'login2' => 'password2'
    ]
];

Все, теперь достаточно указать в контроллере

$this->middleware('http');

P.S. В связке PHP+NGINX авторизация работала нормально. При запуске этого же решения на PHP+Apache авторизация не сохранялась и окно с вводом данных выскакивало при каждом запросе без вывода страницы. Для исправления добавил в .htaccess:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
Комментариев: 0