145

Working on my first Laravel 5 project and not sure where or how to place logic to force HTTPS on my app. The clincher here is that there are many domains pointing to the app and only two out of three use SSL (the third is a fallback domain, long story). So I'd like to handle this in my app's logic rather than .htaccess.

In Laravel 4.2 I accomplished the redirect with this code, located in filters.php:

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

I'm thinking Middleware is where something like this should be implemented but I cannot quite figure this out using it.

Thanks!

UPDATE

If you are using Cloudflare like I am, this is accomplished by adding a new Page Rule in your control panel.

NightMICU
  • 9,000
  • 30
  • 89
  • 121

23 Answers23

286

You can make it works with a Middleware class. Let me give you an idea.

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

Then, apply this middleware to every request adding setting the rule at Kernel.php file, like so:

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'       

];

At sample above, the middleware will redirect every request to https if:

  1. The current request comes with no secure protocol (http)
  2. If your environment is equals to production. So, just adjust the settings according to your preferences.

Cloudflare

I am using this code in production environment with a WildCard SSL and the code works correctly. If I remove && App::environment() === 'production' and test it in localhost, the redirection also works. So, having or not a installed SSL is not the problem. Looks like you need to keep a very hard attention to your Cloudflare layer in order to get redirected to Https protocol.

Edit 23/03/2015

Thanks to @Adam Link's suggestion: it is likely caused by the headers that Cloudflare is passing. CloudFlare likely hits your server via HTTP and passes a X-Forwarded-Proto header that declares it is forwarding a HTTPS request. You need add another line in your Middleware that say...

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

...to trust the headers CloudFlare is sending. This will stop the redirect loop

Edit 27/09/2016 - Laravel v5.3

Just need to add the middleware class into web group 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

    ],
];

Remember that web group is applied to every route by default, so you do not need to set web explicitly in routes nor controllers.

Edit 23/08/2018 - Laravel v5.7

  • To redirect a request depending the environment you can use App::environment() === 'production'. For previous version was env('APP_ENV') === 'production'.
  • Using \URL::forceScheme('https'); actually does not redirect. It just builds links with https:// once the website is rendered.
manix
  • 14,537
  • 11
  • 70
  • 107
  • 7
    This seems to be giving me a redirect loop... looks like it should work, though. I do not know if it makes any difference but we're using a Cloudflare SSL. But I do not think that would change the simple redirect. – NightMICU Feb 09 '15 at 15:29
  • Doing a simple test by using Request in a regular Route::get() and using a conditional to check `$request->isSecure()` always returns false, even when I am connected via https – NightMICU Feb 09 '15 at 15:37
  • 1
    Also, the SSL is not installed directly on the server, it's added by Cloudflare - sort of like a layer. So it goes HTTP request -> Cloudflare -> Our Server. Could this throw off the `isSecure()` check? – NightMICU Feb 09 '15 at 15:39
  • " Looks like you need to keep a very hard attention to your Cloudflare layer in order to get redirected to Https protocol." Can you elaborate on this? – NightMICU Feb 09 '15 at 16:24
  • I do not know how cloudflare works, I mean, you should take a look at its documentation weather the problem resides in their side. Because the code to redirect `http` to `https` in your application actually works. Even, try this code in your localhost machine (where the cloudflare layer is not presented) and you will loook that the redirect works as you expect. – manix Feb 09 '15 at 16:30
  • 4
    @NightMICU I'm not sure if you've solved the issue with the redirect, but it is likely caused by the headers that Cloudflare is passing. CloudFlare likely hits your server via HTTP and passes a X-Forwarded-Proto header that declares it is forwarding a HTTPS request. You need add another line in your Middleware that says `$request->setTrustedProxies( [ $request->getClientIp() ] );` to trust the headers CloudFlare is sending. This will stop the redirect loop. – Adam Link Mar 23 '15 at 18:59
  • 2
    @manix Awesome. Just went through this HTTPS issue this weekend with my own project - that little stuff will frustrate you for hours! – Adam Link Mar 23 '15 at 19:18
  • The CF solution looks a bit unsafe... I used the Fidelooper solution that was made especially for things like this... https://github.com/fideloper/TrustedProxy – insign Aug 27 '15 at 20:14
  • what is getRequestUri()? I cannot find it anywhere in the api. It works, though. But anyway I'm using $request->path() instead. – Curvian Vynes Sep 12 '15 at 15:56
  • Bear in mind that, while the solution provided by @manix is quite good, it has a conflict when the SSL is being forced by Apache (permanent redirection). – facundofarias Dec 21 '15 at 15:16
  • Hello, does this work for multiple namespaces? Assuming I have that middleware in my FrontEnd namespace and I add it to my global middleware in my Kernel.php will it also work for my BackEnd namespace? – user3718908x100 Feb 15 '16 at 09:27
  • This is not working 100% if the public folder is present in the app URL. – Kareem JO Jan 07 '17 at 08:48
  • @KareemJO, "public" folder never should be displayed in the app URL. You may consider review your laravel installation. – manix Jan 08 '17 at 01:36
  • 9
    Excellent answer! Just one detail: It's better to use a 301 redirect to indicate to Google that's a permanent movement. Like: `return redirect()->secure($request->getRequestUri(), 301);` – adriaroca May 04 '17 at 14:14
  • Works fine this solution, i tryed many other without success. tanks – Gabriel Glauber May 19 '17 at 14:26
  • 4
    for those whos under load balancer or proxy can change to secure() to `$request->server('HTTP_X_FORWARDED_PROTO') != 'https'` this works for me – Shiro May 30 '17 at 04:00
  • Adding the middleware to protected $middlewareGroups = ['web' ... was a very good suggestion. Now I don't need to set the middleware to all of my routes but they use it by default. Thanks. – phoenix Jun 08 '17 at 20:54
  • thank you, this Answer and @adriaroca tip helped me a lot – konstantinkoslow Jun 20 '17 at 16:07
  • @manix, seems a bit late, but I think the `!` before `$request->secure()` is not right as we are checking the request is secure and we are in production environment. Is that right? – Sobhan Atar Aug 08 '17 at 16:01
  • 1
    One more information - default APP_ENV for Laravel is "production" instead of "prod". If you didn't set it explicity it .env use "production". Source: config/app.php. – ElChupacabra Aug 30 '17 at 07:11
  • On Cloudflare this did it for me: https://laracasts.com/discuss/channels/forge/lets-encrypt-ssl-too-many-redirects...Crypto > SSL > Full (Strict) setting enabled. – Jared Eitnier Apr 25 '18 at 03:53
  • 1
    Everyone BEWARE! `$request-> getRequestUri()` seems to grab the last part of "//uri", so it can result in phishing attack! For example, if the url is `http://yourdomain.com//phishingdomain.com`, this code will redirect your user back to `https://phishingdomain.com` – pkid169 Dec 03 '18 at 20:23
  • starting Laravel 5.7 Request::setTrustedProxies requieres a seconds parameter `Request::setTrustedProxies([$request->getClientIp()], Request::HEADER_X_FORWARDED_ALL);` – Emanuel A. Aug 13 '20 at 17:54
  • Correct me if I am wrong, but if this is a TLS loadbalancer in front of it then it hits your app always by using port 80 so the `request()->secure()` would always be false and end with redirection loop. You have to trust the headers sent by the proxy here – Bartłomiej Sobieszek Jan 10 '21 at 01:39
77

An other option that worked for me, in AppServiceProvider place this code in the boot method:

\URL::forceScheme('https');

The function written before forceSchema('https') was wrong, its forceScheme

Rob
  • 12,659
  • 4
  • 39
  • 56
Constantin Stan
  • 1,125
  • 9
  • 13
  • 16
    Hey, just found this through googling around - note that in 5.4 it's `\URL::forceScheme('https');` – dev Mar 18 '17 at 06:47
  • 8
    In the same file, you can also do `if($this->app->environment() === 'production'){ $this->app['request']->server->set('HTTPS', true); }` – Rory May 15 '17 at 18:25
  • 2
    did u mean `\URL::forceScheme('https')` – Ernest Okot Jul 11 '17 at 03:35
  • 22
    I'm pretty sure that this is only for building links. This wont force a user to https, it will only serve links prepended with https:// – Weston Watson Oct 18 '17 at 19:54
  • yeah it happened @WestonWatson. kindly share the solution if found – Harat Oct 17 '19 at 21:25
  • Only thing that really worked for me, since a .htaccess config doesn't always redirect sub urls. This does – Patrick Oct 31 '19 at 13:37
  • It's `forceSchema` with an `a` in Laravel 5.2. Otwell likes to randomly rename things to break all our apps. (Which is exactly why I'm still running 5.2 because I don't want to hunt down all the random little things...) – mpen May 25 '20 at 02:25
  • @Rory Only your solution worked for me man. Thanks a lot! – Murat Colyaran Jun 02 '21 at 19:03
42

Alternatively, If you are using Apache then you can use .htaccess file to enforce your URLs to use https prefix. On Laravel 5.4, I added the following lines to my .htaccess file and it worked for me.

RewriteEngine On

RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Assad Ullah Ch
  • 706
  • 7
  • 12
  • 3
    This is not good if you have multiple environments (dev, stage, production) than you need to set SSL on all of them. – Mladen Janjetovic Nov 15 '17 at 10:09
  • @MladenJanjetovic you can use `RewriteCond %{HTTP_HOST} !=localhost` on dev to get around this. – Dan Jul 17 '18 at 04:21
  • 4
    @Dan - Yes, but you will still have to set it up for stage, local (and this is more complicated if developers are using different URLs in local development, i.e. .dev, .local, subdomains,...etc). I would prefer to have that kind of logic in the application. – Mladen Janjetovic Jul 17 '18 at 07:05
  • This should be the right answer. Cannot test it if that rewrite rule has an effect behind TLS proxy, but this should be done by web server, not php code – Bartłomiej Sobieszek Jan 10 '21 at 01:45
24

for laravel 5.4 use this format to get https redirect instead of .htaccess

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        URL::forceScheme('https');
    }
}
Arun Yokesh
  • 1,346
  • 17
  • 19
  • 16
    Just to clarify: 1) these changes should be done in app/Providers/AppServiceProvider.php; 2) this is only to set the links generated inside the app to use SSL, it does not force you to use SSL – phoenix Jun 08 '17 at 20:03
  • Hi, Route is not generating by this method if i click on a button which send me to the next route its not giving me the error 404 – Saket Sinha Sep 11 '17 at 01:19
  • 1
    This is not an https redirect. But it allows the serving of https:// site. If you change it to http:// it will serve as well. – Olu Adeyemo Oct 16 '19 at 07:49
14

Similar to manix's answer but in one place. Middleware to force 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()], 
                Request::HEADER_X_FORWARDED_ALL);

            if (!$request->isSecure()) {
                return redirect()->secure($request->getRequestUri());
            }
        }

        return $next($request);
    }
}
Mladen Janjetovic
  • 13,844
  • 8
  • 72
  • 82
14

What about just using .htaccess file to achieve https redirect? This should be placed in project root (not in public folder). Your server needs to be configured to point at project root directory.

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

I use this for laravel 5.4 (latest version as of writing this answer) but it should continue to work for feature versions even if laravel change or removes some functionality.

Maulik
  • 2,881
  • 1
  • 22
  • 27
  • Chrome gives me an error: Too many redirects.. Seems like this makes a loop – phoenix Jun 08 '17 at 20:05
  • Hi, I've updated answer. Make sure you put this .htaccess in project root directory and point your server (apache config) to project root. – Maulik Jun 09 '17 at 01:33
  • As I said in answer above, this is not good if you have multiple environments (dev, stage, production) than you need to set SSL on all of them. In the app with \URL::forceSchema('https') you can choose when to apply, on which environment – Mladen Janjetovic Nov 15 '17 at 10:09
  • 1
    @MladenJanjetovic you can have different htaccess files for these environments – Burgi Feb 13 '18 at 10:00
  • @Burgi I think this should be part of the app, not to be placed in server config files. And you can apply some logic to enable or disable SSL. htaccess is in version control so I don't see that will work also if you don't have different branches for every environment – Mladen Janjetovic Feb 13 '18 at 13:48
  • 1
    @MladenJanjetovic having it in the application definitely has its advantages, but from an efficiency and speed perspective I'd say it's advantageous to have this in the server config so that you don't have to load up Laravel just for a redirect. Environment-specific configs in a single versioned .htaccess can be achieved by using a rewrite condition to check the domain, something like `RewriteCond %{HTTP_HOST} productiondomain\.com$ [NC]` – Chris Mar 11 '18 at 14:54
  • 1
    I too prefer to place this in .htaccess in the root directory, and as Crhis said, environment-specific settings can be accomplished here, albeit a bit less elegantly than in Mladen's solution. – sveti petar Dec 17 '18 at 15:04
9

This is for Larave 5.2.x and greater. If you want to have an option to serve some content over HTTPS and others over HTTP here is a solution that worked for me. You may wonder, why would someone want to serve only some content over HTTPS? Why not serve everything over HTTPS?

Although, it's totally fine to serve the whole site over HTTPS, severing everything over HTTPS has an additional overhead on your server. Remember encryption doesn't come cheap. The slight overhead also has an impact on your app response time. You could argue that commodity hardware is cheap and the impact is negligible but I digress :) I don't like the idea of serving marketing content big pages with images etc over https. So here it goes. It's similar to what others have suggest above using middleware but it's a full solution that allows you to toggle back and forth between HTTP/HTTPS.

First create a middleware.

php artisan make:middleware ForceSSL

This is what your middleware should look like.

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

Note that I'm not filtering based on environment because I have HTTPS setup for both local dev and production so there is not need to.

Add the following to your routeMiddleware \App\Http\Kernel.php so that you can pick and choose which route group should force 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,
];

Next, I'd like to secure two basic groups login/signup etc and everything else behind 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
});

Confirm that your middlewares are applied to your routes properly from console.

php artisan route:list

Now you have secured all the forms or sensitive areas of your application, the key now is to use your view template to define your secure and public (non https) links.

Based on the example above you would render your secure links as follows -

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

Non secure links can be rendered as

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

What this does is renders a fully qualified URL such as https://yourhost/login and http://yourhost/aboutus

If you were not render fully qualified URL with http and use a relative link url('/aboutus') then https would persists after a user visits a secure site.

Hope this helps!

na-98
  • 909
  • 8
  • 16
7

You can use RewriteRule to force ssl in .htaccess same folder with your index.php

miken32
  • 42,008
  • 16
  • 111
  • 154
Quy Le
  • 2,354
  • 25
  • 18
5

In Laravel 5.1, I used: File: app\Providers\AppServiceProvider.php

public function boot()
{
    if ($this->isSecure()) {
        \URL::forceSchema('https');
    }
}

public function isSecure()
{
    $isSecure = false;
    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
        $isSecure = true;
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
        $isSecure = true;
    }

    return $isSecure;
}

NOTE: use forceSchema, NOT forceScheme

allready4v
  • 163
  • 1
  • 3
  • 8
4

I'm adding this alternative as I suffered a lot with this issue. I tried all different ways and nothing worked. So, I came up with a workaround for it. It might not be the best solution but it does work -

FYI, I am using Laravel 5.6

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

production <- It should be replaced with the APP_ENV value in your .env file

Salvatore
  • 1,435
  • 1
  • 10
  • 21
4

The easiest way would be at the application level. In the file

app/Providers/AppServiceProvider.php

add the following:

use Illuminate\Support\Facades\URL;

and in the boot() method add the following:

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

This should redirect all request to https at the application level.

( Note: this has been tested with laravel 5.5 LTS )

Pinak Saha
  • 56
  • 3
3

in IndexController.php put

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

        return redirect('/');
    }

    return view('index');
}

in AppServiceProvider.php put

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

In AppServiceProvider.php every redirect will be going to URL https and for HTTP request we need once redirect so in IndexController.php Just we need do once redirect.

You particularly don't need to do the work as mentioned in IndexController.php, it is an extra control on the redirection.

GYaN
  • 2,327
  • 4
  • 19
  • 39
3

The answers above didn't work for me, but it appears that Deniz Turan rewrote the .htaccess in a way that works with Heroku's load balancer here: 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]
Phil
  • 31
  • 3
3

Here's how to do it on Heroku

To force SSL on your dynos but not locally, add to end of your .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]

You can test this out on your local machine with:

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

That sets the header X-forwarded to the form it will take on heroku.

i.e. it simulates how a heroku dyno will see a request.

You'll get this response on your local machine:

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

That is a redirect. That is what heroku is going to give back to a client if you set the .htaccess as above. But it doesn't happen on your local machine because X-forwarded won't be set (we faked it with curl above to see what was happening).

mwal
  • 2,803
  • 26
  • 34
2

If you're using CloudFlare, you can just create a Page Rule to always use HTTPS: Force SSL Cloudflare This will redirect every http:// request to https://

In addition to that, you would also have to add something like this to your \app\Providers\AppServiceProvider.php boot() function:

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

This would ensure that every link / path in your app is using https:// instead of http://.

butaminas
  • 672
  • 7
  • 23
2

I am using in 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);
    }
}
fomvasss
  • 21
  • 2
2

A little different approach, tested in Laravel 5.7

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Str;

class ForceHttps
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {    
        if ( !$request->secure() && Str::startsWith(config('app.url'), 'https://') ) {
            return redirect()->secure($request->getRequestUri());
        }
        return $next($request);
    }
}

PS. Code updated based on @matthias-lill's comments.

Zoli
  • 1,081
  • 1
  • 8
  • 28
  • 1
    Works on Laravel 6 too. – Rubens Oct 29 '19 at 14:15
  • 1
    using the env() functions will not work with cached config files. This should point to `config('app.url')` instead. Also, Laravel comes with a very handy string function `Str::startsWith(config('app.url'), 'https://')`. – Matthias Lill Feb 17 '20 at 10:46
2

You can simple go to app -> Providers -> AppServiceProvider.php

add two lines

use Illuminate\Support\Facades\URL;

URL::forceScheme('https');

as shows in the following codes:

use Illuminate\Support\Facades\URL;

class AppServiceProvider extends ServiceProvider
{
   public function boot()
    {
        URL::forceScheme('https');

       // any other codes here, does not matter.
    }
Wria Mohammed
  • 1,433
  • 18
  • 23
1

For Laravel 5.6, I had to change condition a little to make it work.

from:

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

To:

if (empty($_SERVER['HTTPS']) && env('APP_ENV') === 'prod') {
return redirect()->secure($request->getRequestUri());
}
Priyank
  • 11
  • 3
1

This worked out for me. I made a custom php code to force redirect it to https. Just include this code on the 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 } ?>
1

I found out that this worked for me. First copy this code in the .htaccess file.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
Dharman
  • 30,962
  • 25
  • 85
  • 135
  • 1
    Welcome to DO & Thank you for your contribution. Code-only answers without context are generally discouraged on SO. Most Quality answers include an explanation to highlight specific parts of your solution that address the OP's issue & how/why it does so. Most upvotes are accrued over time as future visitors learn something from your post that they are able to apply to their own coding issues. Please consider editing to improve the long term value of your post with some explanation, or even links to documentation. – SherylHohman Feb 12 '21 at 19:41
0

This work for me in Laravel 7.x in 3 simple steps using a middleware:

1) Generate the middleware with command php artisan make:middleware ForceSSL

Middleware

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\App;

class ForceSSL
{
    public function handle($request, Closure $next)
    {
        if (!$request->secure() && App::environment() === 'production') {
            return redirect()->secure($request->getRequestUri());
        }

        return $next($request);
    }
}

2) Register the middleware in routeMiddleware inside Kernel file

Kernel

protected $routeMiddleware = [
    //...
    'ssl' => \App\Http\Middleware\ForceSSL::class,
];

3) Use it in your routes

Routes

Route::middleware('ssl')->group(function() {
    // All your routes here

});

here the full documentation about middlewares

========================

.HTACCESS Method

If you prefer to use an .htaccess file, you can use the following code:

<IfModule mod_rewrite.c>
    RewriteEngine On 
    RewriteCond %{SERVER_PORT} 80 
    RewriteRule ^(.*)$ https://yourdomain.com/$1 [R,L]
</IfModule>

Regards!

Radames E. Hernandez
  • 4,235
  • 27
  • 37
0

The easiest way to redirect to HTTPS with Laravel is by using .htaccess

so all you have to do is add the following lines to your .htaccess file and you are good to go.

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

Make sure you add it before the existing(*default) code found in the .htaccess file, else HTTPS will not work. This is because the existing(default) code already handles a redirect which redirects all traffic to the home page where the route then takes over depending on your URL

so putting the code first means that .htaccess will first redirect all traffic to https before the route takes over

DilanTsasi
  • 186
  • 2
  • 7