Работа над моим первым проектом 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, как я, это достигается добавлением нового правила страницы на панели управления.
Вы можете заставить его работать с классом 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, если:
production
. Поэтому просто настройте параметры в соответствии с вашими предпочтениями. Я использую этот код в рабочей среде с помощью WildCard SSL, и код работает правильно. Если я удалю && App::environment() === 'production'
и протестирую его в localhost, перенаправление также будет работать. Таким образом, наличие или отсутствие установленного SSL не является проблемой. Похоже, вам нужно уделять очень пристальное внимание слою Cloudflare, чтобы перенаправить его на протокол Https.
Благодаря предложению @Adam Link
: это, вероятно, вызвано заголовками, которые пропускает Cloudflare. CloudFlare, вероятно, попадает на ваш сервер через HTTP и передает заголовок X-Forwarded-Proto, который объявляет, что он пересылает запрос HTTPS. Вам нужно добавить еще одну строку в свое промежуточное ПО, которое говорит...
$request->setTrustedProxies( [ $request->getClientIp() ] );
... доверять заголовкам CloudFlare. Это остановит цикл перенаправления
Просто добавьте класс промежуточного программного обеспечения в 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
в маршрутах или контроллерах.
App::environment() === 'production'
. Для предыдущей версии было env('APP_ENV') === 'production'
.\URL::forceScheme('https');
фактически не перенаправляется. Он просто строит ссылки с https://
после рендеринга веб-сайта.$request->isSecure()
всегда возвращает false, даже когда я подключен через https
Другой вариант, который работал у меня, в AppServiceProvider помещает этот код в метод загрузки:
\URL::forceScheme('https');
Функция, написанная до forceSchema ('https'), была неправильной, ее forceScheme
\URL::forceScheme('https');
if($this->app->environment() === 'production'){ $this->app['request']->server->set('HTTPS', true); }
В качестве альтернативы, если вы используете 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');
}
}
Как и в 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);
}
}
Это для 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 будет сохраняться после того, как пользователь посещает безопасный сайт.
Надеюсь, это поможет!
Как насчет использования файла .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 изменяет или удаляет некоторые функции.
в 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 Просто нужно сделать один раз перенаправление
Ответы выше не помогли мне, но, похоже, Дениз Туран переписал .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]
Я использую в 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);
}
}
Если вы используете CloudFlare, вы можете просто создать правило страницы, чтобы всегда использовать HTTPS: Это перенаправляет каждый запрос http://на https://
В дополнение к этому, вы также должны добавить что-то вроде этого в функцию \app\Providers\AppServiceProvider.php boot():
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
Это гарантирует, что каждая ссылка/путь в вашем приложении использует https://вместо http://.
Это сработало для меня. Я создал собственный 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 } ?>
Вы можете использовать RewriteRule для принудительного ssl в.htaccess в той же папке с вашим index.php
Пожалуйста, добавьте в качестве прикрепленного изображения, добавьте его перед всеми правилами других
Для 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());
}
Здесь, как это сделать на 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 не будет установлен (мы подделывали его с завитом выше, чтобы увидеть, что происходит).
Я добавляю эту альтернативу, поскольку я много страдаю от этой проблемы. Я пробовал все по-другому, и ничего не получилось. Итак, я придумал обходной путь для этого. Это может быть не лучшее решение, но оно действительно работает -
FYI, я использую Laravel 5.6
if (App::environment('production')) {
URL::forceScheme('https');
}
production <- Он должен быть заменен значением APP_ENV в вашем.ENV файле
$_SERVER['HTTP_HOST']