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

71

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

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

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

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

Спасибо!

UPDATE

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

  • 0
    Так что же происходит с 3-м доменом? Если вы активируете https на всех маршрутах - будет ли работать третий домен?
  • 0
    Обнаружение этого с помощью $_SERVER['HTTP_HOST']
Показать ещё 2 комментария
Теги:
laravel-5
laravel-routing

16 ответов

166
Лучший ответ

Вы можете заставить его работать с классом Middleware. Позвольте мне дать вам представление.

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); 
    }
}

Затем примените это промежуточное ПО к каждому запросу, добавив настройку правила в файл Kernel.php, например:

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

Я использую этот код в рабочей среде с помощью WildCard 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. Это остановит цикл перенаправления

Редактировать 27/09/2016 - Laravel v5.3

Просто добавьте класс промежуточного программного обеспечения в 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 в маршрутах или контроллерах.

Редактировать 23/08/2018 - Laravel v5.7

  • Чтобы перенаправить запрос в зависимости от среды, вы можете использовать App::environment() === 'production'. Для предыдущей версии было env('APP_ENV') === 'production'.
  • Использование \URL::forceScheme('https'); фактически не перенаправляется. Он просто строит ссылки с https:// после рендеринга веб-сайта.
  • 3
    Это, кажется, дает мне цикл перенаправления ... похоже, он должен работать, хотя. Я не знаю, имеет ли это какое-то значение, но мы используем Cloudflare SSL. Но я не думаю, что это изменит простой редирект.
  • 0
    Выполнение простого теста с использованием Request в обычном Route :: get () и условной проверкой $request->isSecure() всегда возвращает false, даже когда я подключен через https
Показать ещё 21 комментарий
40

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

\URL::forceScheme('https');

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

  • 13
    Эй, только что нашел это через поиск в Google - обратите внимание, что в 5.4 это \URL::forceScheme('https');
  • 2
    В том же файле вы также можете сделать, if($this->app->environment() === 'production'){ $this->app['request']->server->set('HTTPS', true); }
Показать ещё 2 комментария
12

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

RewriteEngine On

RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
  • 1
    Это не хорошо, если у вас есть несколько сред (dev, stage, production), чем вам нужно установить SSL для всех из них.
  • 1
    Также не будет работать для AJAX, (ошибка смешанного режима)
Показать ещё 3 комментария
10

для 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');
    }
}
  • 11
    Просто чтобы уточнить: 1) эти изменения должны быть сделаны в app / Providers / AppServiceProvider.php; 2) это только для установки сгенерированных внутри приложения ссылок на использование SSL, это не заставляет вас использовать SSL
  • 0
    Привет, Маршрут не генерируется этим методом, если я нажимаю на кнопку, которая отправляет меня на следующий маршрут, это не дает мне ошибку 404
9

Как и в manix, но в одном месте. Среднее ПО для принудительного 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);
    }
}
  • 0
    Запрос должен быть статичным?
  • 0
    @jRhesk, вероятно, нет, но, пожалуйста, попробуйте изменить ответ.
4

Это для 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 для локального разработчика и производства, поэтому нет необходимости.

Добавьте в свой маршрутMiddleware\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,
];

Затем я хотел бы защитить две базовые группы login/signup и т.д. и все остальное за промежуточным ПО 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
});

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

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 будет сохраняться после того, как пользователь посещает безопасный сайт.

Надеюсь, это поможет!

3

Как насчет использования файла .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/$1 [L]
</IfModule>

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

  • 0
    Chrome выдает ошибку: слишком много перенаправлений. Похоже, что это делает цикл
  • 0
    Привет, я обновил ответ. Убедитесь, что вы поместили этот .htaccess в корневой каталог проекта и укажите свой сервер (apache config) на корневой каталог проекта.
Показать ещё 5 комментариев
3

в IndexController.php put

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

        return redirect('/');
    }

    return view('index');
}

в приложении AppServiceProvider.php

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

}

В AppServiceProvider.php каждый переадресация будет идти по URL-адресу https и для HTTP-запроса, который нам нужен, как только перенаправление поэтому в IndexController.php Просто нужно сделать один раз перенаправление

  • 0
    Можете ли вы объяснить, как ваш ответ решает вопрос?
  • 0
    Пожалуйста, добавьте это объяснение к вашему ответу.
2

Ответы выше не помогли мне, но, похоже, Дениз Туран переписал .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]
1

Я использую в 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);
    }
}
1

Если вы используете CloudFlare, вы можете просто создать правило страницы, чтобы всегда использовать HTTPS: Изображение 3559 Это перенаправляет каждый запрос http://на https://

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

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

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

1

Это сработало для меня. Я создал собственный PHP-код, чтобы перенаправить его на https. Просто включите этот код в header.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 } ?>
1

Вы можете использовать RewriteRule для принудительного ssl в.htaccess в той же папке с вашим index.php
Пожалуйста, добавьте в качестве прикрепленного изображения, добавьте его перед всеми правилами других Изображение 3560

1

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

от:

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

Для того, чтобы:

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

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

Чтобы принудительно использовать SSL на своих динамиках, но не локально, добавьте в конец своего.htaccess в 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-forwarded в форму, которую он примет на герою.

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

Вы получите ответ на своем локальном компьютере:

<!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>

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

0

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

FYI, я использую Laravel 5.6

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

production <- Он должен быть заменен значением APP_ENV в вашем.ENV файле

Ещё вопросы

Сообщество Overcoder
Наверх
Меню