Ich arbeite an meinem ersten Laravel 5 Projekt und bin mir nicht sicher, wo oder wie ich die Logik platzieren soll, um HTTPS auf meiner App zu erzwingen Drei verwenden SSL (die dritte ist eine Fallback-Domain, eine lange Geschichte). Daher möchte ich dies eher in der Logik meiner App als in .htaccess behandeln.
In Laravel 4.2 habe ich die Weiterleitung mit diesem Code durchgeführt, der sich in filters.php
Befindet:
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
Ich denke, Middleware ist der Ort, an dem so etwas implementiert werden sollte, aber ich kann es nicht ganz herausfinden, wenn ich es benutze.
Vielen Dank!
UPDATE
Wenn Sie Cloudflare wie ich verwenden, wird dies durch Hinzufügen einer neuen Seitenregel in Ihrem Steuerungsfeld erreicht.
Sie können dafür sorgen, dass es mit einer Middleware-Klasse funktioniert. Lass mich dir eine Idee geben.
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);
}
}
Wenden Sie diese Middleware dann auf jede Anforderung an, indem Sie die Regel wie folgt in die Datei Kernel.php
Einfügen:
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'
];
Im obigen Beispiel leitet die Middleware jede Anfrage an https weiter, wenn:
production
ist. Passen Sie die Einstellungen einfach Ihren Wünschen an.Ich verwende diesen Code in einer Produktionsumgebung mit einer WildCard SSL und der Code funktioniert korrekt. Wenn ich && App::environment() === 'production'
entferne und in localhost teste, funktioniert die Umleitung ebenfalls. Ein installiertes SSL zu haben oder nicht, ist also nicht das Problem. Sieht so aus, als müssten Sie Ihre Cloudflare-Ebene sehr genau beobachten, um zum HTTP-Protokoll umgeleitet zu werden.
Dank des Vorschlags von @Adam Link
: Es liegt wahrscheinlich an den Headern, die Cloudflare übergibt. CloudFlare trifft Ihren Server wahrscheinlich über HTTP und übergibt einen X-Forwarded-Proto-Header, der angibt, dass eine HTTPS-Anforderung weitergeleitet wird. Sie müssen eine weitere Zeile in Ihre Middleware einfügen, die besagt ...
$request->setTrustedProxies( [ $request->getClientIp() ] );
... um den Headern zu vertrauen, die CloudFlare sendet. Dies stoppt die Umleitungsschleife
Müssen Sie nur die Middleware-Klasse in web
Gruppe in 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
],
];
Denken Sie daran, dass die Gruppe
web
standardmäßig auf jede Route angewendet wird, sodass Sieweb
nicht explizit in Routen oder Controllern festlegen müssen.
App::environment() === 'production'
verwenden. Für die vorherige Version war env('APP_ENV') === 'production'
.\URL::forceScheme('https');
leitet nicht weiter. Es werden nur Links mit https://
Erstellt, sobald die Website gerendert wurde.Eine andere Option, die für mich funktioniert hat, in AppServiceProvider diesen Code in die Boot-Methode einfügen:
\URL::forceScheme('https');
Die vor forceScheme ('https') geschriebene Funktion war falsch, ihr forceScheme
Wenn Sie Apache verwenden, können Sie alternativ die Datei .htaccess
Verwenden, um zu erzwingen, dass Ihre URLs das Präfix https
verwenden. In Laravel 5.4 habe ich die folgenden Zeilen zu meiner .htaccess
- Datei hinzugefügt und es hat bei mir funktioniert.
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_Host}%{REQUEST_URI} [L,R=301]
verwenden Sie für laravel 5.4 dieses Format, um eine https-Umleitung anstelle von .htaccess zu erhalten
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
}
}
Ähnlich wie die Antwort von Manix, aber an einem Ort. Middleware, um HTTPS zu erzwingen
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);
}
}
Dies gilt für Larave 5.2.x und höher. Wenn Sie die Option haben möchten, einige Inhalte über HTTPS und andere über HTTP bereitzustellen, ist dies eine Lösung, die für mich funktioniert hat. Sie fragen sich vielleicht, warum jemand nur einige Inhalte über HTTPS bereitstellen möchte? Warum nicht alles über HTTPS bereitstellen?
Obwohl es völlig in Ordnung ist, die gesamte Site über HTTPS zu bedienen, hat das Trennen aller Daten über HTTPS einen zusätzlichen Aufwand auf Ihrem Server. Denken Sie daran, Verschlüsselung ist nicht billig. Der geringe Overhead wirkt sich auch auf die Reaktionszeit Ihrer App aus. Man könnte argumentieren, dass Standardhardware billig und die Auswirkungen vernachlässigbar sind, aber ich schweife ab :) Mir gefällt die Idee nicht, große Seiten mit Bildern usw. über https zu vermarkten. Also geht es los. Es ähnelt dem, was andere oben unter Verwendung von Middleware vorgeschlagen haben, aber es ist eine vollständige Lösung, mit der Sie zwischen HTTP/HTTPS hin und her wechseln können.
Erstellen Sie zunächst eine Middleware.
php artisan make:middleware ForceSSL
So sollte Ihre Middleware aussehen.
<?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);
}
}
Beachten Sie, dass ich nicht nach der Umgebung filtere, da ich HTTPS sowohl für die lokale Entwicklung als auch für die Produktion eingerichtet habe, sodass dies nicht erforderlich ist.
Fügen Sie Ihrer routeMiddleware\App\Http\Kernel.php Folgendes hinzu, damit Sie auswählen können, welche Routengruppe SSL erzwingen soll.
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,
];
Als nächstes möchte ich zwei grundlegende Gruppen Login/Signup usw. und alles andere hinter Auth Middleware sichern.
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
});
Vergewissern Sie sich, dass Ihre Middlewares von der Konsole aus ordnungsgemäß auf Ihre Routen angewendet wurden.
php artisan route:list
Nachdem Sie alle Formulare oder vertraulichen Bereiche Ihrer Anwendung gesichert haben, müssen Sie mithilfe Ihrer Ansichtsvorlage Ihre sicheren und öffentlichen (nicht https-) Links definieren.
Anhand des obigen Beispiels würden Sie Ihre sicheren Links wie folgt rendern:
<a href="{{secure_url('/login')}}">Login</a>
<a href="{{secure_url('/signup')}}">SignUp</a>
Nicht sichere Links können als gerendert werden
<a href="{{url('/aboutus',[],false)}}">About US</a></li>
<a href="{{url('/promotion',[],false)}}">Get the deal now!</a></li>
Dadurch wird eine vollständig qualifizierte URL wie https: // yourhost/login und http: // yourhost/aboutus gerendert
Wenn Sie keine vollqualifizierte URL mit http rendern und eine relative Link-URL ('/ aboutus') verwenden, bleibt https bestehen, nachdem ein Benutzer eine sichere Site besucht hat.
Hoffe das hilft!
Wie wäre es einfach mit der Datei . Htaccess, um eine https-Umleitung zu erreichen? Dies sollte im Projektstamm abgelegt werden (nicht im öffentlichen Ordner). Ihr Server muss so konfiguriert sein, dass er auf das Projektstammverzeichnis verweist.
<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>
Ich verwende dies für laravel 5.4 (neueste Version zum Zeitpunkt des Schreibens dieser Antwort), aber es sollte weiterhin für Feature-Versionen funktionieren, auch wenn laravel einige Funktionen ändern oder entfernen .
in IndexController.php setzen
public function getIndex(Request $request)
{
if ($request->server('HTTP_X_FORWARDED_PROTO') == 'http') {
return redirect('/');
}
return view('index');
}
in AppServiceProvider.php setzen
public function boot()
{
\URL::forceSchema('https');
}
In AppServiceProvider.php wird jede Weiterleitung an die URL https gesendet. Für http-Anfragen benötigen wir eine einmalige Weiterleitung. In IndexController.php müssen wir nur eine einmalige Weiterleitung durchführen
Die obigen Antworten haben bei mir nicht funktioniert, aber Deniz Turan hat den .htaccess anscheinend so umgeschrieben, dass er mit Herokus Load Balancer hier funktioniert: https://www.jcore.com/2017/01/29/https-on-heroku-using-htaccess erzwingen /
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_Host}%{REQUEST_URI} [L,R=301]
Für Laravel 5.6 musste ich den Zustand ein wenig ändern, damit es funktionierte.
von:
if (!$request->secure() && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}
Zu:
if (empty($_SERVER['HTTPS']) && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}
Das hat für mich geklappt. Ich habe einen benutzerdefinierten PHP-Code erstellt, um die Weiterleitung an https zu erzwingen. Fügen Sie diesen Code einfach in die header.php ein
<?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 } ?>
Wenn Sie CloudFlare verwenden, können Sie einfach eine Seitenregel erstellen, um immer HTTPS zu verwenden: Dadurch wird jede http: // - Anforderung an https: // umgeleitet.
Darüber hinaus müssten Sie Ihrer boot () -Funktion\app\Providers\AppServiceProvider.php Folgendes hinzufügen:
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
Dies würde sicherstellen, dass jeder Link/Pfad in Ihrer App https: // anstelle von http: // verwendet.
So geht's auf Herok
Fügen Sie zum Erzwingen von SSL auf Ihren Dynos, jedoch nicht lokal, das Ende Ihres .htaccess in public/hinzu:
# 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]
Sie können dies auf Ihrem lokalen Computer testen mit:
curl -H"X-Forwarded-Proto: http" http://your-local-sitename-here
Hierdurch wird der Header X-weitergeleitet und auf die Form gebracht, die er für Heroku annehmen wird.
es wird simuliert, wie ein Heroku-Dyno eine Anfrage sieht.
Sie erhalten diese Antwort auf Ihrem lokalen Computer:
<!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>
Das ist eine Umleitung. Das ist es, was Heroku einem Client zurückgibt, wenn Sie den .htaccess wie oben eingestellt haben. Auf Ihrem lokalen Computer ist dies jedoch nicht der Fall, da X-Forwarding nicht aktiviert ist (wir haben es mit einer Kräuselung oben vorgetäuscht, um zu sehen, was passiert ist).
Ein etwas anderer Ansatz, getestet in 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);
}
}
Ich verwende in Laravel 5.6.28 folgende 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);
}
}
Der einfachste Weg wäre auf der Anwendungsebene. In der Datei
app/Providers/AppServiceProvider.php
fügen Sie Folgendes hinzu:
use Illuminate\Support\Facades\URL;
und fügen Sie in der boot () -Methode Folgendes hinzu:
$this->app['request']->server->set('HTTPS', true);
URL::forceScheme('https');
Dadurch sollten alle Anforderungen auf Anwendungsebene an https umgeleitet werden.
(Hinweis: Dies wurde mit laravel 5.5 LTS) getestet.)
Ich füge diese Alternative hinzu, da ich unter diesem Problem sehr gelitten habe. Ich habe alle möglichen Wege ausprobiert und nichts hat funktioniert. Also habe ich einen Workaround dafür gefunden. Es ist vielleicht nicht die beste Lösung, aber es funktioniert -
Zu Ihrer Information, ich verwende Laravel 5.6
if (App::environment('production')) {
URL::forceScheme('https');
}
production <- Es sollte durch den APP_ENV-Wert in Ihrer .env-Datei ersetzt werden