Laravel 5-перенаправление на HTTPS



работает над моим первым проектом Laravel 5 и не уверен, где и как разместить логику для принудительного HTTPS в моем приложении. Решающим моментом здесь является то, что есть много доменов, указывающих на приложение, и только два из трех используют SSL (третий-резервный домен, длинная история). Поэтому я хотел бы разобраться в логике моего приложения, а не .htaccess.



в Laravel 4.2 я выполнил редирект с этим кодом, расположенным в filters.php:



App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});


Я думаю, что Middleware-это где что-то вроде этого должно быть реализовано, но я не могу понять это, используя его.



спасибо!



обновление



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

1237   16  

16 ответов:

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

namespace MyApp\Http\Middleware;

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

class HttpsProtocol {

    public function handle($request, Closure $next)
    {
            if (!$request->secure() && App::environment() === 'production') {
                return redirect()->secure($request->getRequestUri());
            }

            return $next($request); 
    }
}

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

protected $middleware = [
    'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
    'Illuminate\Cookie\Middleware\EncryptCookies',
    'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
    'Illuminate\Session\Middleware\StartSession',
    'Illuminate\View\Middleware\ShareErrorsFromSession',

    // appending custom middleware 
    'MyApp\Http\Middleware\HttpsProtocol'       

];

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

  1. текущий запрос поставляется без защищенного протокола (http)
  2. если ваша среда равна production. Так, как раз отрегулируйте установки согласно ваше пожелание.

Cloudflare

я использую этот код в производственной среде с шаблоном SSL и код работает правильно. Если я удалю && App::environment() === 'production' и проверить его в localhost, перенаправление также работает. Таким образом, наличие или отсутствие установленного SSL не является проблемой. Похоже, вам нужно очень внимательно следить за своим слоем Cloudflare, чтобы перенаправиться на протокол Https.

изменить 23/03/2015

спасибо @Adam Linkпредложение: это, вероятно, вызвано заголовками, которые Cloudflare передает. CloudFlare, вероятно, попадает на ваш сервер через HTTP и передает заголовок X-Forwarded-Proto, который объявляет, что он пересылает запрос HTTPS. Вам нужно добавить еще одну строку в вашем промежуточном программном обеспечении, которые говорят...

$request->setTrustedProxies( [ $request->getClientIp() ] ); 

... доверять заголовкам CloudFlare отправляет. Это остановит цикл перенаправления

Edit 27/09/2016-Laravel v5. 3

просто нужно добавить класс middleware в web группа в kernel.php file:

protected $middlewareGroups = [
    'web' => [
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,

        // here
        \MyApp\Http\Middleware\HttpsProtocol::class

    ],
];

помните, что web группа применяется к каждому маршруту по умолчанию, поэтому вам не нужно устанавливать web явно в маршрутах, ни контроллеров.

Edit 23/08/2018-Laravel v5. 7

  • для перенаправления запроса в зависимости от окружающей среды вы можете использовать App::environment() === 'production'. Для предыдущей версии был env('APP_ENV') === 'production'.
  • используя \URL::forceScheme('https'); на самом деле не перенаправляет. Он просто строит ссылки с https:// после того, как сайт отображается.

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

\URL::forceScheme('https');

функция, написанная до forceSchema ('https') была неправильной, ее forceScheme

кроме того, если вы используете Apache, то вы можете использовать .htaccess файл для принудительного использования URL-адресов https префикс. На Laravel 5.4 я добавил следующие строки в свой .htaccess файл и это сработало для меня.

RewriteEngine On

RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

для laravel 5.4 используйте этот формат, чтобы получить перенаправление https вместо .htaccess

namespace App\Providers;

use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        URL::forceScheme('https');
    }
}

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

namespace App\Http\Middleware;

use Closure;

use Illuminate\Http\Request;

class ForceHttps
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (!app()->environment('local')) {
            // for Proxies
            Request::setTrustedProxies([$request->getClientIp()]);

            if (!$request->isSecure()) {
                return redirect()->secure($request->getRequestUri());
            }
        }

        return $next($request);
    }
}

это для Larave 5.2.X и выше. Если вы хотите иметь возможность обслуживать некоторые материалы по HTTPS и другие по HTTP, вот решение, которое сработало для меня. Вы можете задаться вопросом, почему кто-то хочет обслуживать только некоторый контент по HTTPS? Почему бы не обслуживать все через HTTPS?

хотя, это совершенно нормально, чтобы обслуживать весь сайт по HTTPS, разделяя все по HTTPS имеет дополнительные накладные расходы на вашем сервере. Помните, что шифрование не дешево. Пренебрежение накладные расходы также влияют на время отклика приложения. Вы можете утверждать, что товарное оборудование дешево, и влияние незначительно, но я отвлекаюсь :) мне не нравится идея обслуживания больших страниц маркетингового контента с изображениями и т. д. по https. Так что вот оно. Это похоже на то, что другие предлагают выше, используя промежуточное программное обеспечение, но это полное решение, которое позволяет переключаться между HTTP/HTTPS.

создать промежуточное.

php artisan make:middleware ForceSSL

это ваши промежуточное ПО должно выглядеть так.

<?php

namespace App\Http\Middleware;

use Closure;

class ForceSSL
{

    public function handle($request, Closure $next)
    {

        if (!$request->secure()) {
            return redirect()->secure($request->getRequestUri());
        }

        return $next($request);
    }
}

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

добавьте следующее в routeMiddleware \App\Http\Kernel.php, чтобы вы могли выбрать, какая группа маршрутов должна принудительно использовать SSL.

    protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'forceSSL' => \App\Http\Middleware\ForceSSL::class,
];

далее, я хотел бы обеспечить две основные группы входа / регистрации и т. д. И все остальное за Auth промежуточное программное обеспечение.

Route::group(array('middleware' => 'forceSSL'), function() {
/*user auth*/
Route::get('login', 'AuthController@showLogin');
Route::post('login', 'AuthController@doLogin');

// Password reset routes...
Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');
Route::post('password/reset', 'Auth\PasswordController@postReset');

//other routes like signup etc

});


Route::group(['middleware' => ['auth','forceSSL']], function()
 {
Route::get('dashboard', function(){
    return view('app.dashboard');
});
Route::get('logout', 'AuthController@doLogout');

//other routes for your application
});

убедитесь, что ваши middlewares применяются к вашим маршрутам правильно из консоли.

php artisan route:list

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

на основе приведенного выше примера вы будете отображать свои безопасные ссылки следующим образом -

<a href="{{secure_url('/login')}}">Login</a>
<a href="{{secure_url('/signup')}}">SignUp</a>

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

<a href="{{url('/aboutus',[],false)}}">About US</a></li>
<a href="{{url('/promotion',[],false)}}">Get the deal now!</a></li>

то, что это делает, представляет собой полный URL-адрес, такой как https://yourhost/login и http://yourhost/aboutus

если вы не отображали полный URL-адрес с помощью http и использовали относительный url-адрес ссылки('/aboutus'), то https будет сохраняться после посещения пользователем безопасного сайта.

надеюсь, что это помогает!

в IndexController.php put

public function getIndex(Request $request)
{
    if ($request->server('HTTP_X_FORWARDED_PROTO') == 'http') {

        return redirect('/');
    }

    return view('index');
}

в AppServiceProvider.php put

public function boot()
{
    \URL::forceSchema('https');

}

В AppServiceProvider.php каждый редирект будет идти на url https и для http-запроса нам нужно один раз перенаправить так что в IndexController.php просто нам нужно сделать один раз редирект

Как насчет того, чтобы просто использовать .htaccess файл для достижения перенаправления https? Это должно быть помещено в корень проекта (не в общую папку). Ваш сервер должен быть настроен так, чтобы он указывал на корневой каталог проекта.

<IfModule mod_rewrite.c>
   RewriteEngine On
   # Force SSL
   RewriteCond %{HTTPS} !=on
   RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
   # Remove public folder form URL
   RewriteRule ^(.*)$ public/ [L]
</IfModule>

Я использую это для laravel 5.4 (последняя версия на момент написания этого ответа), но он должен продолжать работать для версий функций, даже если laravel изменяет или удаляет некоторые функции.

ответы выше не работали для меня, но похоже, что Дениз Туран переписал.htaccess таким образом, что работает с балансировщиком нагрузки Heroku здесь: https://www.jcore.com/2017/01/29/force-https-on-heroku-using-htaccess/

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

вот как это сделать на Heroku

чтобы заставить SSL на вашем dynos, но не локально, добавьте в конец вашего .htaccess in public/:

# Force https on heroku...
# Important fact: X-forwarded-Proto will exist at your heroku dyno but wont locally.
# Hence we want: "if x-forwarded exists && if its not https, then rewrite it":
RewriteCond %{HTTP:X-Forwarded-Proto} .
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

вы можете проверить это на своем локальном компьютере с помощью:

curl -H"X-Forwarded-Proto: http" http://your-local-sitename-here

это устанавливает заголовок X-пересылается в форму, которую он примет на heroku.

т. е. он имитирует, как heroku dyno будет видеть запрос.

вы получите этот ответ на вашем местном машина:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://tm3.localhost:8080/">here</a>.</p>
</body></html>

это перенаправление. Это то, что heroku собирается вернуть клиенту, если вы установите .htaccess, как указано выше. Но это не происходит на вашей локальной машине, потому что X-forwarded не будет установлен (мы подделали его с помощью curl выше, чтобы увидеть, что происходит).

для Laravel 5.6 мне пришлось немного изменить состояние, чтобы заставить его работать.

от:

if (!$request->secure() && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}

To:

if (empty($_SERVER['HTTPS']) && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}

вы можете использовать RewriteRule для принудительного ssl .htaccess та же папка с вашим индексом.РНР
пожалуйста, добавьте как прикрепить изображение, добавить его перед всеми правят другие setting ssl .htaccess

это сработало для меня. Я сделал пользовательский php-код, чтобы заставить перенаправить его на https. Просто включите этот код в заголовок.php

<?php
if (isset($_SERVER['HTTPS']) &&
    ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
    isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
    $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $protocol = 'https://';
}
else {
  $protocol = 'http://';
}
$notssl = 'http://';
if($protocol==$notssl){
    $url = "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";?>
    <script> 
    window.location.href ='<?php echo $url?>';
    </script> 
 <?php } ?>

Если вы используете CloudFlare, вы можете просто создать правило страницы, чтобы всегда использовать HTTPS: Force SSL Cloudflare Это будет перенаправлять каждого HTTP:// запрос к HTTPS://

в дополнение к этому, Вам также придется добавить что-то вроде этого в ваш \app\Providers\AppServiceProvider.php boot () функция:

if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
     \URL::forceScheme('https');
}

это гарантирует, что каждая ссылка / путь в вашем приложении использует https:// вместо http://.

Я использую в Laravel 5.6.28 следующее промежуточное ПО:

namespace App\Http\Middleware;

use App\Models\Unit;
use Closure;
use Illuminate\Http\Request;

class HttpsProtocol
{
    public function handle($request, Closure $next)
    {
        $request->setTrustedProxies([$request->getClientIp()], Request::HEADER_X_FORWARDED_ALL);

        if (!$request->secure() && env('APP_ENV') === 'prod') {
            return redirect()->secure($request->getRequestUri());
        }

        return $next($request);
    }
}

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

к вашему сведению, я использую Laravel 5.6

if (App::environment('production')) {
    URL::forceScheme('https');
}

production

Comments

    Ничего не найдено.