Laravel 5 - เปลี่ยนเส้นทางไปยัง HTTPS


127

กำลังทำงานกับโปรเจ็กต์ Laravel 5 แรกของฉันและไม่แน่ใจว่าจะวางตรรกะเพื่อบังคับ HTTPS บนแอปของฉันได้ที่ไหน ข้อสรุปคือมีหลายโดเมนที่ชี้ไปที่แอปและมีเพียงสองในสามเท่านั้นที่ใช้ SSL (โดเมนที่สามเป็นโดเมนสำรองเรื่องยาว) ดังนั้นฉันต้องการจัดการสิ่งนี้ด้วยตรรกะของแอปของฉันมากกว่า. htaccess

ใน Laravel 4.2 ฉันเปลี่ยนเส้นทางสำเร็จด้วยรหัสนี้ซึ่งอยู่ในfilters.php:

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

ฉันคิดว่ามิดเดิลแวร์เป็นสิ่งที่ควรนำมาใช้ แต่ฉันไม่สามารถเข้าใจได้ว่าจะใช้มัน

ขอบคุณ!

UPDATE

หากคุณใช้ Cloudflare เหมือนฉันสิ่งนี้สามารถทำได้โดยการเพิ่ม Page Rule ใหม่ในแผงควบคุมของคุณ


แล้วจะเกิดอะไรขึ้นกับโดเมนที่ 3? หากคุณบังคับ https ในทุกเส้นทาง - โดเมนที่ 3 จะทำงานต่อไปหรือไม่
Laurence

ตรวจพบว่าด้วย$_SERVER['HTTP_HOST']
NightMICU

กฎของหน้า cloudflare ใช้เวลานานเท่าใดจึงจะมีผล
CodeGuru

โอ้ฉันต้องเปิดพร็อกซีในการตั้งค่า DNS ฮ่าฮ่า!
CodeGuru

คำตอบ:


253

คุณสามารถทำให้มันใช้งานได้กับคลาสมิดเดิลแวร์ ให้ฉันเป็นความคิด

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 ถ้า:

  1. คำขอปัจจุบันไม่มีโปรโตคอลที่ปลอดภัย (http)
  2. productionหากสภาพแวดล้อมของคุณคือเท่ากับ ดังนั้นเพียงปรับการตั้งค่าตามความต้องการของคุณ

Cloudflare

ฉันใช้รหัสนี้ในสภาพแวดล้อมการใช้งานจริงด้วย WildCard SSL และรหัสทำงานได้อย่างถูกต้อง ถ้าฉันลบ&& App::environment() === 'production'และทดสอบใน localhost การเปลี่ยนเส้นทางก็ใช้ได้เช่นกัน ดังนั้นการมีหรือไม่มี SSL ติดตั้งไม่ใช่ปัญหา ดูเหมือนว่าคุณต้องให้ความสนใจอย่างมากกับเลเยอร์ Cloudflare ของคุณเพื่อที่จะเปลี่ยนเส้นทางไปยังโปรโตคอล Https

แก้ไข 23/03/2558

ขอบคุณ@Adam Linkคำแนะนำ: น่าจะเกิดจากส่วนหัวที่ Cloudflare ส่งผ่าน CloudFlare มีแนวโน้มที่จะเข้าถึงเซิร์ฟเวอร์ของคุณผ่าน HTTP และส่งผ่านส่วนหัว X-Forwarded-Proto ที่ประกาศว่ากำลังส่งต่อคำขอ HTTPS คุณต้องเพิ่มบรรทัดอื่นในมิดเดิลแวร์ของคุณที่ระบุว่า ...

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

... เพื่อความไว้วางใจส่วนหัวที่ CloudFlare กำลังส่ง การดำเนินการนี้จะหยุดการวนรอบการเปลี่ยนเส้นทาง

แก้ไข 27/09/2016 - Laravel v5.3

เพียงแค่ต้องเพิ่มคลาสมิดเดิลแวร์ลงใน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อย่างชัดเจนในเส้นทางหรือตัวควบคุม

แก้ไข 23/08/2018 - Laravel v5.7

  • เพื่อเปลี่ยนเส้นทางคำขอขึ้นอยู่กับสภาพแวดล้อมที่คุณสามารถApp::environment() === 'production'ใช้ได้ env('APP_ENV') === 'production'สำหรับรุ่นก่อนหน้านี้
  • การใช้\URL::forceScheme('https');จริงไม่เปลี่ยนเส้นทาง เพียงแค่สร้างลิงก์https://เมื่อมีการแสดงผลเว็บไซต์

5
ดูเหมือนว่าจะทำให้ฉันวนรอบการเปลี่ยนเส้นทาง ... ดูเหมือนว่ามันจะใช้งานได้ ฉันไม่รู้ว่ามันสร้างความแตกต่างหรือไม่ แต่เรากำลังใช้ Cloudflare SSL แต่ฉันไม่คิดว่าจะเปลี่ยนการเปลี่ยนเส้นทางง่ายๆ
NightMICU

3
@NightMICU ฉันไม่แน่ใจว่าคุณได้แก้ไขปัญหาด้วยการเปลี่ยนเส้นทางหรือไม่ แต่น่าจะเกิดจากส่วนหัวที่ Cloudflare กำลังส่งผ่าน CloudFlare มีแนวโน้มที่จะเข้าถึงเซิร์ฟเวอร์ของคุณผ่าน HTTP และส่งผ่านส่วนหัว X-Forwarded-Proto ที่ประกาศว่ากำลังส่งต่อคำขอ HTTPS คุณต้องเพิ่มอีกบรรทัดในมิดเดิลแวร์ของคุณที่ระบุว่า$request->setTrustedProxies( [ $request->getClientIp() ] );เชื่อถือส่วนหัวที่ CloudFlare กำลังส่ง การดำเนินการนี้จะหยุดการวนรอบการเปลี่ยนเส้นทาง
Adam Link

2
@manix น่ากลัว เพิ่งแก้ไขปัญหา HTTPS ในสุดสัปดาห์นี้ด้วยโครงการของฉันเองสิ่งเล็ก ๆ น้อย ๆ นั้นจะทำให้คุณหงุดหงิดไปหลายชั่วโมง!
Adam Link

8
ตอบโจทย์สุด ๆ ! รายละเอียดเพียงอย่างเดียว: ควรใช้การเปลี่ยนเส้นทาง 301 เพื่อระบุให้ Google ทราบว่าเป็นการเคลื่อนไหวถาวร ชอบ:return redirect()->secure($request->getRequestUri(), 301);
adriaroca

4
สำหรับผู้ที่อยู่ภายใต้ตัวจัดสรรภาระงานหรือพร็อกซีสามารถเปลี่ยนเป็นความปลอดภัย () เพื่อใช้$request->server('HTTP_X_FORWARDED_PROTO') != 'https'งานได้สำหรับฉัน
ชิโระ

63

ตัวเลือกอื่นที่ใช้ได้ผลสำหรับฉันใน AppServiceProvider วางรหัสนี้ในวิธีการบูต:

\URL::forceScheme('https');

ฟังก์ชั่นที่เขียนก่อน forceSchema ('https') นั้นผิด ForceScheme


16
เฮ้เพิ่งพบสิ่งนี้ผ่าน googling รอบ ๆ - โปรดทราบว่าใน 5.4 เป็น\URL::forceScheme('https');
dev

5
ในไฟล์เดียวกันคุณสามารถทำได้if($this->app->environment() === 'production'){ $this->app['request']->server->set('HTTPS', true); }
Rory

2
คุณหมายถึง\URL::forceScheme('https')
Ernest Okot

17
ฉันค่อนข้างมั่นใจว่านี่เป็นเพียงการสร้างลิงก์เท่านั้น สิ่งนี้จะไม่บังคับให้ผู้ใช้ใช้ https แต่จะให้บริการเฉพาะลิงก์ที่นำหน้าด้วย https: //
Weston Watson

ใช่มันเกิดขึ้น @WestonWatson กรุณาแบ่งปันวิธีแก้ปัญหาหากพบ
Harat

33

หรือหากคุณใช้ Apache คุณสามารถใช้.htaccessไฟล์เพื่อบังคับให้ URL ของคุณใช้httpsคำนำหน้า ใน Laravel 5.4 ฉันได้เพิ่มบรรทัดต่อไปนี้ใน.htaccessไฟล์ของฉันและมันก็ใช้ได้สำหรับฉัน

RewriteEngine On

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

2
สิ่งนี้ไม่ดีหากคุณมีหลายสภาพแวดล้อม (dev, stage, production) เกินกว่าที่คุณจะต้องตั้งค่า SSL ให้กับสภาพแวดล้อมทั้งหมด
Mladen Janjetovic

@MladenJanjetovic คุณสามารถใช้RewriteCond %{HTTP_HOST} !=localhostกับ dev เพื่อหลีกเลี่ยงสิ่งนี้
แดน

3
@ แดน - ใช่ แต่คุณจะต้องตั้งค่าสำหรับพื้นที่งานในพื้นที่ (และจะซับซ้อนกว่านี้หากนักพัฒนาใช้ URL ที่แตกต่างกันในการพัฒนาท้องถิ่นเช่น. dev, .local, โดเมนย่อย, ... ฯลฯ ) ฉันอยากจะมีตรรกะแบบนั้นในแอปพลิเคชัน
Mladen Janjetovic

16

สำหรับ 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');
    }
}

15
เพียงเพื่อชี้แจง: 1) ควรทำการเปลี่ยนแปลงเหล่านี้ใน app / Providers / AppServiceProvider.php; 2) นี่เป็นเพียงการตั้งค่าลิงก์ที่สร้างขึ้นภายในแอปเพื่อใช้ SSL เท่านั้น แต่ไม่ได้บังคับให้คุณใช้ SSL
ฟีนิกซ์

สวัสดีเส้นทางไม่ได้สร้างขึ้นโดยวิธีนี้หากฉันคลิกที่ปุ่มที่ส่งฉันไปยังเส้นทางถัดไปมันไม่ได้ให้ข้อผิดพลาด 404 แก่ฉัน
Saket Sinha

นี่ไม่ใช่การเปลี่ยนเส้นทาง https แต่อนุญาตให้แสดงไซต์ https: // หากคุณเปลี่ยนเป็น http: // ก็จะให้บริการเช่นกัน
ฟรังก์

12

คล้ายกับคำตอบของ 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);
    }
}

คำขอจำเป็นต้องคงที่หรือไม่
GFxJamal

@jRhesk อาจจะไม่ได้ แต่โปรดลองแก้ไขคำตอบ
Mladen Janjetovic

เริ่มต้น Laravel 5.6 Request :: setTrustedProxies ต้องการพารามิเตอร์วินาทีRequest::setTrustedProxies([$request->getClientIp()], Request::HEADER_X_FORWARDED_ALL);
Emanuel A.

8

นี่คือสำหรับ 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 สำหรับทั้ง dev ในเครื่องและการใช้งานจริงดังนั้นจึงไม่จำเป็นต้องทำ

เพิ่มสิ่งต่อไปนี้ใน routeMiddleware \ 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,
];

ต่อไปฉันต้องการรักษาความปลอดภัยการเข้าสู่ระบบ / สมัครใช้งานกลุ่มพื้นฐานสองกลุ่มและอื่น ๆ ที่อยู่เบื้องหลังมิดเดิลแวร์ 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 จะยังคงอยู่หลังจากผู้ใช้เข้าชมไซต์ที่ปลอดภัย

หวังว่านี่จะช่วยได้!


7

สิ่งที่เกี่ยวกับการใช้ไฟล์. 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 จะเปลี่ยนหรือลบฟังก์ชันบางอย่างออกไป


Chrome ทำให้ฉันมีข้อผิดพลาด: มีการเปลี่ยนเส้นทางมากเกินไป .. ดูเหมือนว่าจะวนซ้ำ
ฟีนิกซ์

สวัสดีฉันได้อัปเดตคำตอบแล้ว ตรวจสอบให้แน่ใจว่าคุณใส่. htaccess นี้ในไดเร็กทอรีรูทของโปรเจ็กต์และชี้เซิร์ฟเวอร์ของคุณ (apache config) ไปที่รูทของโปรเจ็กต์
Maulik Gangani

1
@MladenJanjetovic คุณสามารถมีไฟล์ htaccess ที่แตกต่างกันสำหรับสภาพแวดล้อมเหล่านี้
Burgi

1
@MladenJanjetovic การมีไว้ในแอปพลิเคชันนั้นมีข้อดีอย่างแน่นอน แต่จากมุมมองด้านประสิทธิภาพและความเร็วฉันว่ามันเป็นประโยชน์ที่จะมีสิ่งนี้ในการกำหนดค่าเซิร์ฟเวอร์เพื่อที่คุณจะได้ไม่ต้องโหลด Laravel เพียงเพื่อเปลี่ยนเส้นทาง การกำหนดค่าเฉพาะสภาพแวดล้อมใน. htaccess เวอร์ชันเดียวสามารถทำได้โดยใช้เงื่อนไขการเขียนซ้ำเพื่อตรวจสอบโดเมนเช่นRewriteCond %{HTTP_HOST} productiondomain\.com$ [NC]
คริส

1
ฉันชอบวางสิ่งนี้ไว้ใน. htaccess ในไดเรกทอรีรากเช่นกันและดังที่ Crhis กล่าวว่าการตั้งค่าเฉพาะสภาพแวดล้อมสามารถทำได้ที่นี่แม้ว่าจะดูหรูหราน้อยกว่าในโซลูชันของ Mladen เล็กน้อย
jovan

6

คุณสามารถใช้ RewriteRule เพื่อบังคับให้ ssl ใน. htaccess โฟลเดอร์เดียวกันกับ index.php ของคุณ
โปรดเพิ่มเป็นแนบรูปภาพเพิ่มก่อนกฎอื่น ๆ ทั้งหมด การตั้งค่า ssl .htaccess


4

ฉันกำลังเพิ่มทางเลือกนี้เนื่องจากฉันประสบปัญหานี้มาก ฉันลองวิธีต่างๆทั้งหมดแล้วและไม่มีอะไรได้ผล ดังนั้นฉันจึงหาวิธีแก้ปัญหาสำหรับมัน อาจไม่ใช่ทางออกที่ดีที่สุด แต่ได้ผล -

FYI ฉันใช้ Laravel 5.6

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

production <- ควรแทนที่ด้วยค่า APP_ENV ในไฟล์. env ของคุณ


3

ใน IndexController.php ใส่

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 เพียงแค่เราต้องทำเมื่อเปลี่ยนเส้นทาง


คุณอธิบายได้ไหมว่าคำตอบของคุณช่วยแก้คำถามได้อย่างไร
soundslikeodd

โปรดเพิ่มคำอธิบายนี้ในคำตอบของคุณ
soundslikeodd

3

คำตอบข้างต้นไม่ได้ผลสำหรับฉัน แต่ดูเหมือนว่า Deniz Turan จะเขียน. htaccess ใหม่ด้วยวิธีที่ทำงานร่วมกับโหลดบาลานเซอร์ของ Heroku ที่นี่: https://www.jcore.com/2017/01/29/force-https -ON-Heroku โดยใช้-htaccess /

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

2

นี่คือวิธีการทำใน Heroku

ในการบังคับใช้ SSL บน dynos ของคุณ แต่ไม่ใช่ในเครื่องให้เพิ่มที่ส่วนท้ายของ. htaccess ของคุณในที่สาธารณะ /:

# 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 ที่ส่งต่อไปยังแบบฟอร์มที่จะใช้กับ heroku

กล่าวคือเป็นการจำลองว่า heroku dyno จะเห็นคำขออย่างไร

คุณจะได้รับคำตอบนี้ในเครื่องของคุณ:

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

นั่นคือการเปลี่ยนเส้นทาง นั่นคือสิ่งที่ heroku จะคืนให้กับลูกค้าหากคุณตั้งค่า. htaccess ไว้ข้างต้น แต่มันไม่ได้เกิดขึ้นในเครื่องของคุณเนื่องจาก X-forwarded จะไม่ถูกตั้งค่า (เราแกล้งทำเป็น curl ด้านบนเพื่อดูว่าเกิดอะไรขึ้น)


2

หากคุณใช้ CloudFlare คุณสามารถสร้างกฎของเพจเพื่อใช้ HTTPS ได้ตลอดเวลา: บังคับ SSL Cloudflare สิ่งนี้จะเปลี่ยนเส้นทาง http: // ทุกคำขอไปยัง https: //

นอกจากนั้นคุณจะต้องเพิ่มสิ่งนี้ในฟังก์ชัน \ app \ Providers \ AppServiceProvider.php boot () ของคุณ:

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

เพื่อให้แน่ใจว่าทุกลิงค์ / เส้นทางในแอปของคุณใช้ https: // แทน http: //


2

ฉันใช้ใน 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);
    }
}

2

แนวทางที่แตกต่างกันเล็กน้อยทดสอบใน 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 อัปเดตโค้ดตามความคิดเห็นของ @ matthias-lill


1
ใช้ได้กับ Laravel 6 ด้วย
Rubens

1
การใช้ฟังก์ชัน env () จะไม่ทำงานกับไฟล์กำหนดค่าที่แคชไว้ สิ่งนี้ควรชี้ไปที่config('app.url')แทน นอกจากนี้ Laravel Str::startsWith(config('app.url'), 'https://')มาพร้อมกับฟังก์ชั่นสตริงที่มีประโยชน์มาก
Matthias Lill

1

สำหรับ 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());
}

1

สิ่งนี้ได้ผลสำหรับฉัน ฉันสร้างรหัส 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 } ?>

1

วิธีที่ง่ายที่สุดคือในระดับแอปพลิเคชัน ในไฟล์

app/Providers/AppServiceProvider.php

เพิ่มสิ่งต่อไปนี้:

use Illuminate\Support\Facades\URL;

และใน boot () วิธีการเพิ่มสิ่งต่อไปนี้:

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

สิ่งนี้ควรเปลี่ยนเส้นทางคำขอทั้งหมดไปที่ https ที่ระดับแอปพลิเคชัน

(หมายเหตุ: ได้รับการทดสอบด้วย laravel 5.5 LTS)


1

คุณสามารถไปที่แอพ -> ผู้ให้บริการ -> AppServiceProvider.php

เพิ่มสองบรรทัด

ใช้ Illuminate \ Support \ Facades \ URL;

URL :: forceScheme ( 'https');

ตามที่แสดงในรหัสต่อไปนี้:

use Illuminate\Support\Facades\URL;

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

       // any other codes here, does not matter.
    }

0

งานนี้สำหรับฉันในLaravel 7.xใน3 ขั้นตอนง่ายๆโดยใช้มิดเดิลแวร์:

1) สร้างมิดเดิลแวร์ด้วยคำสั่ง php artisan make:middleware ForceSSL

มิดเดิ้ล

<?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) ลงทะเบียนมิดเดิลแวร์ในrouteMiddlewareไฟล์ Kernel

เมล็ด

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

3) ใช้ในเส้นทางของคุณ

เส้นทาง

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

});

นี่คือเอกสารฉบับเต็มเกี่ยวกับมิดเดิลแวร์

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

.HTACCESS วิธี

หากคุณต้องการใช้.htaccessไฟล์คุณสามารถใช้รหัสต่อไปนี้:

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

ความนับถือ!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.