私の最初のLaravel 5プロジェクトで作業していて、どこにどのようにロジックを配置して私のアプリにHTTPSを強制するかがわからない。ここでのクリンチャーは、アプリを指しているドメインが多数あり、3つのうち2つだけがSSLを使用していることです(3つ目はフォールバックドメイン、長い話)。そのため、これを.htaccessではなく、アプリのロジックで処理したいと思います。
Laravel 4.2では、filters.php
にあるこのコードでリダイレクトを達成しました。
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
私はミドルウェアがこのようなものが実装されるべき場所であると思っていますが、私はそれを使ってこれを理解することはできません。
ありがとうございます。
UPDATE
私のようにCloudflareを使用している場合は、コントロールパネルに新しいページルールを追加することでこれを実現できます。
あなたはそれをミドルウェアクラスで動作させることができます。私にあなたに考えを与えましょう。
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にリダイレクトします。
production
と等しい場合だから、あなたの好みに合わせて設定を調整するだけです。私は本番環境でWildCard SSLを使用してこのコードを使用していますが、コードは正しく機能します。 && App::environment() === 'production'
を削除してlocalhostでテストすると、リダイレクトも機能します。したがって、SSLがインストールされているかどうかは問題ではありません。 Httpsプロトコルにリダイレクトされるためには、Cloudflareレイヤに非常に注意を払う必要があるようです。
@Adam Link
の提案のおかげで:それはおそらくCloudflareが渡しているヘッダーによって引き起こされます。 CloudFlareはおそらくHTTP経由であなたのサーバーにヒットし、HTTPSリクエストを転送していることを宣言するX-Forwarded-Protoヘッダーを渡します。ミドルウェアに次のような行を追加する必要があります。
$request->setTrustedProxies( [ $request->getClientIp() ] );
... CloudFlareが送信しているヘッダーを信頼する。これはリダイレクトループを停止します
ミドルウェアクラスをkernel.php file
のweb
グループに追加するだけです。
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
を明示的に設定する必要はありません。
App::environment() === 'production'
を使用できます。以前のバージョンではenv('APP_ENV') === 'production'
でした。\URL::forceScheme('https');
を使用しても実際にはリダイレクトされません。 Webサイトがレンダリングされたら、https://
とのリンクを作成するだけです。AppServiceProviderで私のために働いた他のオプションは、ブートメソッドにこのコードを配置します。
\URL::forceScheme('https');
ForceScheme( 'https')の前に書かれた関数が間違っていました、そのforceScheme
あるいは、Apacheを使用している場合は、.htaccess
ファイルを使用して、URLにhttps
プレフィックスを使用するよう強制することができます。 Laravel 5.4では、私は私の.htaccess
ファイルに次の行を追加しました、そしてそれは私のために働きました。
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_Host}%{REQUEST_URI} [L,R=301]
laravel 5.4では、.htaccessの代わりにhttpsリダイレクトを取得するためにこのフォーマットを使用します
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
}
}
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);
}
}
これはLarave 5.2.x以降用です。 HTTPSを介してコンテンツを提供し、HTTPを介して他のコンテンツを提供するためのオプションが必要な場合は、ここで解決策が役立ちます。あなたは不思議に思うかもしれません、なぜ誰かが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設定を持っているので、必要はありません。
次の行を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,
];
次に、2つの基本的なグループログイン/サインアップなどと、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>
これにより、 https:// yourhost/login や http:// yourhost/aboutus のような完全修飾URLが表示されます。
完全修飾URLをhttpでレンダリングしておらず、相対リンクURL( '/ aboutus')を使用している場合は、ユーザーがセキュリティで保護されたサイトにアクセスしてもhttpsが保持されます。
お役に立てれば!
Httpsリダイレクトを実現するために。htaccessファイルを使用するだけの場合はどうでしょうか。これは(パブリックフォルダではなく)プロジェクトルートに配置する必要があります。サーバーはプロジェクトのルートディレクトリを指すように設定する必要があります。
<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が変更されたり機能が削除されたりしても機能バージョンでは引き続き機能します。
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では、すべてのリダイレクトがhttps URLに送信され、httpリクエストの場合は1回リダイレクトする必要があるため、IndexController.phpでは1回リダイレクトする必要があります
上記の答えは私にはうまくいきませんでしたが、Deniz TuranがHerokuのロードバランサーと一緒に動作するように.htaccessを書き換えたようです: 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]
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());
}
これは私のためにうまくいきました。私はそれをhttpsに強制的にリダイレクトするためのカスタムphpコードを作りました。このコードを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 } ?>
CloudFlareを使用している場合は、常にHTTPSを使用するようにページルールを作成するだけです。 これはすべてのhttp://リクエストをhttps://にリダイレクトします。
それに加えて、あなたはあなたの\ app\Providers\AppServiceProvider.php boot()関数に次のようなものを追加する必要があるでしょう。
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
これにより、アプリ内のすべてのリンク/パスがhttp://ではなくhttps://を使用するようになります。
これがHerokuのやり方です
ローカルではなくあなたのダイナにSSLを強制するには、public /のあなたの.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
これは、ヘッダをherokuで受け取る形式にX転送するように設定します。
つまり、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>
それはリダイレクトです。上記のように.htaccessを設定した場合、それがherokuがクライアントに返すことになります。しかし、X転送が設定されていないので、それはあなたのローカルマシンでは起こりません(何が起こっているのかを見るために上記のcurlで偽造しました)。
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);
}
}
私は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);
}
}
私はこの問題に多く苦しんだので、私はこの代替を加えています。私はいろいろな方法を試しましたが、何もうまくいきませんでした。だから、私はそれのための回避策を思い付きました。それは最善の解決策ではないかもしれませんがそれはうまくいきます -
参考までに、Laravel 5.6を使用しています
if (App::environment('production')) {
URL::forceScheme('https');
}
production < - .envファイルのAPP_ENV値に置き換えます
最も簡単な方法はアプリケーションレベルです。ファイル内
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でテスト済みです)