Laravel 5-przekierowanie na HTTPS

Pracuję nad moim pierwszym projektem Laravel 5 i nie wiem, gdzie i jak umieścić logikę, aby wymusić HTTPS w mojej aplikacji. Najważniejsze jest to, że istnieje wiele domen wskazujących na aplikację, a tylko dwie na trzy używają SSL (trzecia to domena zapasowa, długa historia). Chciałbym więc zająć się tym w logice mojej aplikacji, a nie .htaccess.

W Laravel 4.2 wykonałem przekierowanie z tym kodem, znajdującym się w filters.php:

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

Myślę, że Middleware jest tam, gdzie coś takiego powinno być zaimplementowane, ale nie mogę tego zrozumieć, używając go.

Dzięki!

UPDATE

Jeśli używasz Cloudflare jak ja, osiąga się to poprzez dodanie nowej reguły strony w Panelu sterowania.

Author: NightMICU, 2015-02-09

16 answers

Możesz sprawić, że będzie działać z klasą Middleware. Podam ci pomysł.

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

Następnie zastosuj tę middleware do każdego żądania dodając ustawienie reguły w pliku Kernel.php, tak:

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'       

];
[16]} w powyższym przykładzie, oprogramowanie pośredniczące przekieruje każde żądanie do https, jeśli:
    W tym celu należy skontaktować się z naszym Biurem Obsługi Klienta.]}
  1. Jeśli Twoje środowisko jest równe production. Po prostu dostosuj ustawienia zgodnie z własnymi preferencjami.

Cloudflare

Używam tego kodu w środowisku produkcyjnym z wieloznacznym SSL i Kod działa poprawnie. Jeśli usunę && App::environment() === 'production' i przetestuję go w localhost, przekierowanie również działa. Tak więc posiadanie zainstalowanego SSL nie stanowi problemu. Wygląda na to, że musisz zwrócić szczególną uwagę na warstwę Cloudflare, aby zostać przekierowanym do protokołu Https.

Edycja 23/03/2015

Dzięki sugestii @Adam Link: prawdopodobnie jest to spowodowane przez nagłówki ta chmura mija. CloudFlare prawdopodobnie trafi na twój serwer przez HTTP i przekazuje nagłówek X-Forwarded-Proto, który deklaruje, że przesyła żądanie HTTPS. Musisz dodać kolejną linijkę w swoim Middleware, która mówi...

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

...zaufać nagłówkom, które wysyła CloudFlare. Spowoduje to zatrzymanie pętli przekierowania

[[28]}Edycja 27/09/2016-Laravel v5. 3

Wystarczy dodać klasę middleware do web grupy w 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

    ],
];

Pamiętaj, że web grupa jest domyślnie stosowane do każdej trasy, więc nie trzeba jawnie ustawiać web w routes ani kontrolerach.

[[28]} Edycja 23/08/2018-Laravel v5. 7
  • aby przekierować żądanie w zależności od środowiska, możesz użyć App::environment() === 'production'. Dla poprzedniej wersji był env('APP_ENV') === 'production'.
  • użycie \URL::forceScheme('https'); w rzeczywistości nie przekierowuje. Po prostu buduje linki z https://, gdy strona jest renderowana.
 158
Author: manix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-23 22:53:08

Inna opcja, która mi zadziałała, w AppServiceProvider umieść ten kod w metodzie boot:

\URL::forceScheme('https');

Funkcja napisana przed forceSchema ('https') była błędna, jej forceScheme

 39
Author: Constantin Stan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-02 12:02:49

Alternatywnie, jeśli używasz Apache ' a, możesz użyć pliku .htaccess, Aby wymusić użycie prefiksu https. Na Laravel 5.4, dodałem następujące linie do mojego pliku .htaccess i zadziałało dla mnie.

RewriteEngine On

RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
 12
Author: Assad Ullah Ch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-26 12:07:08

Dla laravel 5.4 użyj tego formatu, aby uzyskać przekierowanie https zamiast .htaccess

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        URL::forceScheme('https');
    }
}
 10
Author: Arun Yokesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-28 09:50:51

Podobne do odpowiedzi manixa, ale w jednym miejscu. Middleware, aby wymusić 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);
    }
}
 9
Author: Mladen Janjetovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-14 17:00:32

To dla Larave 5.2.x i większe. Jeśli chcesz mieć opcję serwowania niektórych treści przez HTTPS, a innych przez HTTP, oto rozwiązanie, które działało dla mnie. Możesz się zastanawiać, dlaczego ktoś chciałby serwować tylko niektóre treści przez HTTPS? Dlaczego nie podawać wszystkiego przez HTTPS?

Chociaż serwowanie całej witryny przez HTTPS jest całkowicie w porządku, zerwanie wszystkiego przez HTTPS ma dodatkowy narzut na serwerze. Pamiętaj, że szyfrowanie nie jest tanie. Lekkie nadproża również ma wpływ na czas reakcji aplikacji. Można argumentować, że sprzęt jest tani, a wpływ jest znikomy, ale dygresję :) nie podoba mi się pomysł serwowania treści marketingowych dużych stron z obrazkami itp przez https. Więc zaczyna się. Jest to podobne do tego, co inni sugerują powyżej za pomocą oprogramowania pośredniczącego, ale jest to pełne rozwiązanie, które pozwala przełączać się między HTTP / HTTPS.

Najpierw Utwórz oprogramowanie pośredniczące.

php artisan make:middleware ForceSSL
Tak powinno wyglądać oprogramowanie pośrednie.
<?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);
    }
}

Zauważ, że nie filtruję w oparciu o środowisko, ponieważ mam konfigurację HTTPS zarówno dla lokalnego dewelopera, jak i produkcji, więc nie ma takiej potrzeby.

Dodaj następujące elementy do jądra routeMiddleware \ App \ Http\.php, dzięki czemu możesz wybrać, która grupa tras powinna wymusić 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,
];

Następnie chciałbym zabezpieczyć dwie podstawowe grupy login / signup itp. i wszystko inne za AUTH middleware.

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

Potwierdź, że Twoje środki są stosowane do Twoich tras prawidłowo z konsoli.

php artisan route:list

Teraz zabezpieczyłeś wszystkie formularze lub wrażliwe obszary aplikacji, kluczem jest teraz użycie szablonu widoku do zdefiniowania bezpiecznych i publicznych linków (bez https).

Na podstawie powyższego przykładu możesz renderować swoje bezpieczne linki w następujący sposób -

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

Niezabezpieczone linki mogą być renderowane jako

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

To, co robi, to renderuje w pełni kwalifikowany adres URL, taki jak https://yourhost/login i http://yourhost/aboutus

Jeśli nie renderujesz w pełni kwalifikowanego adresu URL z http i używasz względnego adresu URL łącza('/aboutus'), https będzie trwał po wizycie użytkownika w bezpiecznej witrynie.

Mam nadzieję, że to pomoże!
 4
Author: na-98,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-27 14:45:55

W IndexController.php put

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

        return redirect('/');
    }

    return view('index');
}

W AppServiceProvider.php put

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

}

W AppServiceProvider.php każde przekierowanie będzie przejść do url https i dla żądania http musimy raz przekierowanie tak w IndexController.php wystarczy zrobić raz przekierowanie

 3
Author: Artur Qaramyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-05 19:22:41

A co z używaniem .htaccess plik, aby uzyskać przekierowanie https? To powinno być umieszczone w katalogu głównym projektu (nie w folderze publicznym). Twój serwer musi być skonfigurowany tak, aby wskazywał na główny katalog projektu.

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

Używam tego dla laravel 5.4 (najnowsza wersja od napisania tej odpowiedzi), ale powinno nadal działać dla wersji funkcji, nawet jeśli Laravel zmieni lub usunie jakąś funkcjonalność.

 3
Author: Maulik Gangani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-09 01:32:04

Powyższe odpowiedzi nie zadziałały dla mnie, ale wygląda na to, że Deniz Turan przepisał .htaccess w sposób, który działa z Heroku load balancer tutaj: 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]
 2
Author: Phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 14:50:28

Oto Jak to zrobić na Heroku

Aby wymusić SSL na dynos, ale nie lokalnie, Dodaj do końca swojego .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]

Możesz to przetestować na lokalnym komputerze za pomocą:

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

, który ustawia nagłówek X-przekazany do postaci, którą przyjmie na heroku.

Czyli symuluje, jak hamownia heroku zobaczy żądanie.

Otrzymasz tę odpowiedź na lokalnej maszynie:

<!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>
To jest przekierowanie. To właśnie heroku da powrót do klienta, Jeśli ustawisz .htaccess jak wyżej. Ale to nie dzieje się na twojej lokalnej maszynie, ponieważ x-forward nie będzie ustawiony(sfałszowaliśmy to z curl powyżej, aby zobaczyć, co się dzieje).
 1
Author: mwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 17:32:02

Dla Laravel 5.6, musiałem zmienić trochę stan, aby to działało.

From:

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

Do:

if (empty($_SERVER['HTTPS']) && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}
 1
Author: Priyank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-29 11:08:58

Możesz użyć RewriteRule, aby wymusić ssl .htaccess ten sam folder z Twoim indeksem.php
Proszę Dodać jako załączony obrazek, dodać go przed wszystkimi innymi ustawianie ssl .htaccess

 1
Author: Quy Le,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-01 04:47:30

To mi się udało. Zrobiłem niestandardowy kod php, aby wymusić przekierowanie go do https. Wystarczy umieścić ten kod w nagłówku.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
Author: Geeky Ashim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-03 19:04:32

Jeśli używasz CloudFlare, możesz po prostu utworzyć regułę strony, aby zawsze używać HTTPS: Force SSL Cloudflare Spowoduje to przekierowanie każdego żądania http://na https: / /

Oprócz tego, musisz również dodać coś takiego do swojego \app \ Providers \ AppServiceProvider.funkcja php boot ():

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

Zapewni to, że każde łącze / ścieżka w Twojej aplikacji będzie używać https: / / zamiast http://.

 1
Author: butaminas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-05 21:24:04

Używam w Laravel 5.6.28 next middleware:

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
Author: fomvasss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-30 15:35:39

Dodaję tę alternatywę, ponieważ wiele wycierpiałem z tym problemem. Próbowałem różnych sposobów i nic nie działało. Więc wymyśliłem obejście tego problemu. Może nie jest to najlepsze rozwiązanie, ale działa-

FYI, używam Laravel 5.6

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

Production

 0
Author: thebrownkid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-21 11:10:35