Промежуточное программное обеспечение Laravel 'auth' устанавливает неправильные данные сеанса 'url.intended' при работе за обратным прокси - PullRequest
0 голосов
/ 19 июня 2019

Справочная информация:

Я разрабатываю приложение Laravel 5.8, работающее внутри контейнера Docker на сервере за обратным прокси-сервером, пересылая запросы в приложение на основе подкаталога URL, например, example.org/laravel/.

Все (маршруты, HTTPS-ссылки, ресурсы и т. Д.) Работает нормально, кроме перенаправления на нужную страницу после входа в систему.

Я выполнил правильную генерацию URL для маршрутов, ресурсов и т. Д., Используя

app('url')->forceRootUrl(config('app.url'));  // https://example.org/laravel/
app('url')->forceScheme('https');

Моя проблема:

Предположим, я определил маршрут /foo с промежуточным программным обеспечением auth. Когда я выхожу из системы и посещаю example.org/laravel/foo, я правильно перенаправлен на example.org/laravel/login, но после входа я перенаправлен на example.org/foo, который не существует.

Результаты расследования:

Доступ к /foo при выходе из системы

  1. auth промежуточное ПО выдает AuthenticatedException, которое перехватывается в Illuminate\Routing\Pipeline и передается в Illuminate\Foundation\Exceptions\Handler::unauthenticated() (через Handler::render())
  2. Handler::unauthenticated() возвращает redirect()->guest() (Illuminate\Routing\Redirector::guest())
  3. Redirector::guest() устанавливает для сеансового ключа url.intended значение $this->generator->full() (Illuminate\Http\Request::fullUrl() через Illuminate\Routing\UrlGenerator::full())
  4. Request::fullUrl() звонки Symfony\Component\HttpFoundation\Request::getUri() (через $this->url())
  5. Request::getUri() строит URL из $_SERVER и запрашивает данные заголовка (см. Ниже) следующим образом ($qs: строка запроса):
$this->getScheme().'://'.$this->getHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs
---
getScheme()   => 'http'         // As $_SERVER['HTTPS'] is not set
getHttpHost() => 'example.org'  // From $this->headers->get('HOST')
getBaseUrl()  => ''             // From $_SERVER['SCRIPT_NAME']   *[1]
getPathInfo() => '//foo'        // From $_SERVER['REQUEST_URI']
$qs           => ''             // From $_SERVER['QUERY_STRING']
---
*[1]: In Symfony\Component\HttpFoundation\Request::prepareBaseUrl():
      $baseUrl    = 'index.php' (L. 1745)
      $requestUri = '//foo'     (L. 1768)
      $prefix     = '/'         (L. 1778)
   => return ''                 (L. 1780)
  1. В результате сеанс url.intended устанавливается на http://example.org//foo вместо http(s)://example.org/laravel/foo

$_SERVER данные (выдержка):

"HTTP_HOST" => "example.org"
"SERVER_NAME" => "example.org"
"QUERY_STRING" => ""
"REQUEST_URI" => "//foo"
"SCRIPT_NAME" => "/index.php"

Версии пакета Exact Composer:

  • Laravel / framework: v5.8.3
  • symfony / http-foundation: v4.2.4

1 Ответ

0 голосов
/ 19 июня 2019

Вы можете настроить промежуточное ПО, сгруппировать все свои маршруты внутри и перейти в промежуточное ПО примерно так:

namespace MyApp\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\App;

class SecureRedirect{

 public function handle($request, Closure $next)
  {
        if (!$request->secure()) {
            return redirect()->secure($request->getRequestUri());
        }

        return $next($request); 
  }
}

или добавить его в начало вашего файла маршрутов

if (env('APP_ENV') === 'production') {
    URL::forceSchema('https');
}
...