Подтвердить что ты не робот

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

Спасибо!

UPDATE

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

4b9b3361

Ответ 1

Вы можете заставить его работать с классом 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:// после рендеринга веб-сайта.

Ответ 2

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

\URL::forceScheme('https');

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

Ответ 3

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

RewriteEngine On

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

Ответ 4

для 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');
    }
}

Ответ 5

Как и в 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);
    }
}

Ответ 6

Это для 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', '[email protected]');
Route::post('login', '[email protected]');

// Password reset routes...
Route::get('password/reset/{token}', 'Auth\[email protected]');
Route::post('password/reset', 'Auth\[email protected]');

//other routes like signup etc

});


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

//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 сохранится после посещения пользователем защищенного сайта.

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

Ответ 7

Как насчет использования файла .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 изменяет или удаляет некоторые функции.

Ответ 8

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

Ответ 9

в 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 Просто нужно сделать один раз перенаправление

Ответ 10

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

Ответ 11

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

Ответ 12

Для 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());
}

Ответ 13

Это сработало для меня. Я создал собственный 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 } ?>

Ответ 14

Если вы используете 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://.

Ответ 15

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

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

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

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

Ответ 16

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

Ответ 17

Немного другой подход, протестированный в Laravel 5.7

<?php

namespace App\Http\Middleware;

use Closure;

class ForceHttps
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $app_url = env('APP_URL');

        if ( !$request->secure() && substr($app_url, 0, 8) === 'https://' ) {
            return redirect()->secure($request->getRequestUri());
        }
        return $next($request);
    }
}

Ответ 18

Самый простой способ - на уровне приложений. В файле

app/Providers/AppServiceProvider.php

добавить следующее:

use Illuminate\Support\Facades\URL;

и в методе boot() добавьте следующее:

$this->app['request']->server->set('HTTPS', true);
URL::forceScheme('https');

Это должно перенаправить весь запрос на https на уровне приложения.

(Примечание: это было протестировано с Laravel 5.5 LTS)