Je travaille sur mon premier projet Laravel 5 sans savoir où et comment placer la logique pour forcer HTTPS sur mon application. L’essentiel ici est qu’il existe de nombreux domaines pointant vers l’application et que seulement deux sur trois utilisent le protocole SSL (le troisième est un domaine de repli, histoire longue). Je voudrais donc gérer cela dans la logique de mon application plutôt que .htaccess.
Dans Laravel 4.2 j'ai effectué la redirection avec ce code, situé dans filters.php
:
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
Je pense que Middleware est l'endroit où quelque chose comme ceci devrait être implémenté mais je ne peux pas comprendre cela en l'utilisant.
Merci!
UPDATE
Si vous utilisez Cloudflare comme je le suis, pour cela, ajoutez une nouvelle règle de page dans votre panneau de configuration.
Vous pouvez le faire fonctionner avec une classe Middleware. Laisse-moi te donner une idée.
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);
}
}
Ensuite, appliquez ce middleware à chaque demande ajoutant la définition de la règle dans le fichier Kernel.php
, comme suit:
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'
];
Dans l'exemple ci-dessus, le middleware redirigera chaque requête vers https si:
production
. Alors, ajustez simplement les paramètres en fonction de vos préférences.J'utilise ce code dans un environnement de production avec une WildCard SSL et le code fonctionne correctement. Si je supprime && App::environment() === 'production'
et le teste dans localhost, la redirection fonctionne également. Donc, avoir ou non un SSL installé n'est pas le problème. On dirait que vous devez garder une très grande attention sur votre couche Cloudflare afin d'être redirigé vers le protocole Https.
Grâce à la suggestion de @Adam Link
: elle est probablement causée par les en-têtes que Cloudflare passe. CloudFlare frappe probablement votre serveur via HTTP et passe un en-tête X-Forwarded-Proto qui déclare qu'il transfère une demande HTTPS. Vous devez ajouter une autre ligne dans votre middleware qui dit ...
$request->setTrustedProxies( [ $request->getClientIp() ] );
... faire confiance aux en-têtes que CloudFlare envoie. Cela arrêtera la boucle de redirection
Il suffit d’ajouter la classe de middleware au groupe web
de 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
],
];
N'oubliez pas que le groupe
web
est appliqué à chaque route par défaut. Vous n'avez donc pas besoin de définir explicitementweb
dans les routes ni dans les contrôleurs.
App::environment() === 'production'
. Pour la version précédente était env('APP_ENV') === 'production'
.\URL::forceScheme('https');
ne redirige pas réellement. Il ne fait que créer des liens avec https://
une fois que le site Web est rendu.Une autre option qui a fonctionné pour moi, dans AppServiceProvider, placez ce code dans la méthode de démarrage:
\URL::forceScheme('https');
La fonction écrite avant forceScheme ('https') était fausse, forceScheme
Si vous utilisez Apache, vous pouvez également utiliser le fichier .htaccess
pour que vos URL utilisent le préfixe https
. Sur Laravel 5.4, j'ai ajouté les lignes suivantes à mon fichier .htaccess
et cela a fonctionné pour moi.
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_Host}%{REQUEST_URI} [L,R=301]
for laravel 5.4 utilisez ce format pour obtenir une redirection https au lieu de .htaccess
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
}
}
Semblable à la réponse de manix mais à un endroit. Middleware pour forcer 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);
}
}
C'est pour Larave 5.2.x et supérieur. Si vous souhaitez avoir la possibilité de servir du contenu via HTTPS et d’autres via HTTP, voici une solution qui a fonctionné pour moi. Vous vous demandez peut-être pourquoi quelqu'un voudrait ne servir que du contenu via HTTPS? Pourquoi ne pas tout servir via HTTPS?
Bien que ce soit tout à fait correct de servir le site entier via HTTPS, tout couper sur HTTPS entraîne une surcharge supplémentaire sur votre serveur. Rappelez-vous que le cryptage n'est pas bon marché. La légère surcharge a également un impact sur le temps de réponse de votre application. Vous pourriez dire que le matériel de base est bon marché et que l'impact est négligeable, mais je m'éloigne du sujet :) Je n'aime pas l'idée de servir du contenu marketing sur de grandes pages avec des images, etc. au-dessus de https. Alors voilà. C'est semblable à ce que d'autres suggèrent d'utiliser un middleware, mais c'est une solution complète qui vous permet de basculer entre HTTP et HTTPS.
Commencez par créer un middleware.
php artisan make:middleware ForceSSL
Voici à quoi devrait ressembler votre middleware.
<?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);
}
}
Notez que je ne filtre pas en fonction de l'environnement car j'ai la configuration HTTPS pour le développement local et la production, il n'y en a donc pas besoin.
Ajoutez les éléments suivants à votre fichier routeMiddleware\App\Http\Kernel.php afin que vous puissiez choisir quel groupe de routes doit forcer le protocole 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,
];
Ensuite, j'aimerais sécuriser deux groupes de base de connexion/inscription, etc. et tout le reste derrière le middleware 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
});
Confirmez que vos middlewares sont correctement appliqués à vos itinéraires depuis la console.
php artisan route:list
Maintenant que vous avez sécurisé tous les formulaires ou les zones sensibles de votre application, vous devez maintenant utiliser votre modèle de vue pour définir vos liens sécurisés et publics (non https).
Sur la base de l'exemple ci-dessus, vous rendrez vos liens sécurisés comme suit:
<a href="{{secure_url('/login')}}">Login</a>
<a href="{{secure_url('/signup')}}">SignUp</a>
Les liens non sécurisés peuvent être rendus comme
<a href="{{url('/aboutus',[],false)}}">About US</a></li>
<a href="{{url('/promotion',[],false)}}">Get the deal now!</a></li>
Cela rend une URL pleinement qualifiée telle que https: // votrehôte/login et http: // votrehôte/aboutus
Si vous ne présentiez pas d'URL qualifiée complète avec http et n'utilisiez pas d'URL de lien relatif ("/ aboutus"), https persisterait alors lorsqu'un utilisateur visitait un site sécurisé.
J'espère que cela t'aides!
Qu'en est-il de simplement utiliser . Htaccess fichier pour obtenir la redirection https? Cela devrait être placé dans la racine du projet (pas dans un dossier public). Votre serveur doit être configuré pour pointer vers le répertoire racine du projet.
<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>
J'utilise ceci pour laravel 5.4 (dernière version au moment de l'écriture de cette réponse), mais cela devrait continuer à fonctionner pour les versions de fonctions, même si laravel change ou supprime certaines fonctionnalités.
dans IndexController.php put
public function getIndex(Request $request)
{
if ($request->server('HTTP_X_FORWARDED_PROTO') == 'http') {
return redirect('/');
}
return view('index');
}
dans AppServiceProvider.php put
public function boot()
{
\URL::forceSchema('https');
}
Dans AppServiceProvider.php, chaque redirection sera dirigée vers l’URL https et pour la requête HTTP, nous avons besoin d’une redirection unique. Dans IndexController.php, nous avons simplement besoin de redirection unique.
Les réponses ci-dessus n'ont pas fonctionné pour moi, mais il apparaît que Deniz Turan a récrit le fichier .htaccess d'une manière qui fonctionne avec l'équilibreur de charge de Heroku ici: 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]
Pour Laravel 5.6, j'ai dû changer un peu de condition pour que cela fonctionne.
de:
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());
}
Cela a fonctionné pour moi. J'ai créé un code php personnalisé pour le forcer à le rediriger vers https. Il suffit d'inclure ce code sur le 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 } ?>
Si vous utilisez CloudFlare, vous pouvez simplement créer une règle de page pour toujours utiliser HTTPS: Cela redirigera chaque requête http: // vers https: //
En plus de cela, vous devrez également ajouter quelque chose comme ceci à votre fonction\app\Providers\AppServiceProvider.php boot ():
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
Cela garantirait que chaque lien/chemin dans votre application utilise https: // au lieu de http: //.
Voici comment faire sur Herok
Pour forcer SSL sur votre dynos mais pas localement, ajoutez à la fin de votre .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]
Vous pouvez tester cela sur votre machine locale avec:
curl -H"X-Forwarded-Proto: http" http://your-local-sitename-here
Cela définit l'en-tête X-transmis à la forme qu'il prendra sur heroku.
c'est-à-dire qu'il simule comment un dyno de heroku verra une requête.
Vous obtiendrez cette réponse sur votre ordinateur local:
<!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>
C'est une redirection. C'est ce que heroku va redonner à un client si vous définissez le .htaccess comme ci-dessus. Mais cela ne se produit pas sur votre ordinateur local car X-forwarded ne sera pas défini (nous le simulons avec curl ci-dessus pour voir ce qui se passait).
Une approche légèrement différente, testée dans 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);
}
}
J'utilise dans Laravel 5.6.28 le prochain 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);
}
}
Le moyen le plus simple serait au niveau de l'application. Dans le fichier
app/Providers/AppServiceProvider.php
ajoutez ce qui suit:
use Illuminate\Support\Facades\URL;
et dans la méthode boot (), ajoutez ce qui suit:
$this->app['request']->server->set('HTTPS', true);
URL::forceScheme('https');
Cela devrait rediriger toutes les demandes vers https au niveau de l'application.
(Remarque: ceci a été testé avec laravel 5.5 LTS)
J'ajoute cette alternative car j'ai beaucoup souffert de ce problème. J'ai essayé de différentes manières et rien n'a fonctionné. Donc, je suis venu avec une solution de contournement pour cela. Ce n'est peut-être pas la meilleure solution, mais ça marche -
Pour info, j'utilise Laravel 5.6
if (App::environment('production')) {
URL::forceScheme('https');
}
production <- Il doit être remplacé par la valeur APP_ENV dans votre fichier .env