php Laravel 5 - 重定向到 HTTPS
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28402726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel 5 - redirect to HTTPS
提问by NightMICU
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.
在我的第一个 Laravel 5 项目中工作,但不确定在哪里或如何放置逻辑以在我的应用程序上强制使用 HTTPS。这里的关键是有许多域指向应用程序,并且只有三分之二使用 SSL(第三个是后备域,长话短说)。所以我想在我的应用程序的逻辑中而不是 .htaccess 中处理这个问题。
In Laravel 4.2 I accomplished the redirect with this code, located in filters.php
:
在 Laravel 4.2 中,我使用以下代码完成了重定向,位于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.
如果您像我一样使用 Cloudflare,这是通过在您的控制面板中添加一个新的页面规则来实现的。
回答by manix
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:
然后,将此中间件应用于在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'
];
At sample above, the middleware will redirect every request to https if:
在上面的示例中,如果出现以下情况,中间件会将每个请求重定向到 https:
- The current request comes with no secure protocol (http)
- If your environment is equals to
production
. So, just adjust the settings according to your preferences.
- 当前请求没有安全协议 (http)
- 如果您的环境等于
production
. 因此,只需根据您的喜好调整设置即可。
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.
我在带有 WildCard SSL 的生产环境中使用此代码,并且代码工作正常。如果我&& App::environment() === 'production'
在本地主机中删除并测试它,重定向也有效。因此,是否安装 SSL 都不是问题。看起来您需要非常注意您的 Cloudflare 层才能重定向到 Https 协议。
Edit 23/03/2015
编辑 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...
感谢@Adam Link
的建议:这很可能是由 Cloudflare 传递的标头引起的。CloudFlare 可能通过 HTTP 访问您的服务器并传递一个 X-Forwarded-Proto 标头,声明它正在转发 HTTPS 请求。您需要在中间件中添加另一行说...
$request->setTrustedProxies( [ $request->getClientIp() ] );
...to trust the headers CloudFlare is sending. This will stop the redirect loop
...信任 CloudFlare 发送的标头。这将停止重定向循环
Edit 27/09/2016 - Laravel v5.3
编辑 27/09/2016 - Laravel v5.3
Just need to add the middleware class into web
group in kernel.php file
:
只需要将中间件类添加到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
],
];
Remember that
web
group is applied to every route by default, so you do not need to setweb
explicitly in routes nor controllers.
请记住,
web
默认情况下 group 应用于每个路由,因此您不需要web
在路由或控制器中明确设置。
Edit 23/08/2018 - Laravel v5.7
编辑 23/08/2018 - Laravel v5.7
- To redirect a request depending the environment you can use
App::environment() === 'production'
. For previous version wasenv('APP_ENV') === 'production'
. - Using
\URL::forceScheme('https');
actually does not redirect. It just builds links withhttps://
once the website is rendered.
- 要根据环境重定向请求,您可以使用
App::environment() === 'production'
. 对于以前的版本是env('APP_ENV') === 'production'
. - 使用
\URL::forceScheme('https');
实际上不会重定向。它只是https://
在网站呈现后建立链接。
回答by Constantin Stan
An other option that worked for me, in AppServiceProvider place this code in the boot method:
另一个对我有用的选项,在 AppServiceProvider 中将此代码放在引导方法中:
\URL::forceScheme('https');
The function written before forceScheme('https') was wrong, its forceScheme
forceScheme('https') 之前写的函数写错了,它的forceScheme
回答by Assad Ullah Ch
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.
或者,如果您使用的是 Apache,那么您可以使用.htaccess
file 来强制您的 URL 使用https
前缀。在 Laravel 5.4 上,我将以下几行添加到我的.htaccess
文件中,它对我有用。
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
回答by Arun Yokesh
for laravel 5.4 use this format to get https redirect instead of .htaccess
对于 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');
}
}
回答by Mladen Janjetovic
Similar to manix's answer but in one place. Middleware to force 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);
}
}
回答by na-98
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?
这适用于 Larave 5.2.x 及更高版本。如果您想选择通过 HTTPS 提供某些内容而通过 HTTP 提供其他内容,这里有一个对我有用的解决方案。您可能想知道,为什么有人只想通过 HTTPS 提供某些内容?为什么不通过 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.
虽然通过 HTTPS 为整个站点提供服务是完全没问题的,但是通过 HTTPS 切断所有内容会给您的服务器带来额外的开销。请记住,加密并不便宜。轻微的开销也会影响您的应用程序响应时间。你可能会争辩说商品硬件很便宜,影响可以忽略不计,但我离题了:) 我不喜欢通过 https 提供带有图像等的营销内容大页面的想法。所以就到这里了。它类似于上面使用中间件的其他人建议,但它是一个完整的解决方案,允许您在 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.
请注意,我没有根据环境进行过滤,因为我为本地开发和生产都设置了 HTTPS,因此不需要。
Add the following to your routeMiddleware \App\Http\Kernel.php so that you can pick and choose which route group should force SSL.
将以下内容添加到您的 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,
];
Next, I'd like to secure two basic groups login/signup etc and everything else behind Auth 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
});
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.
现在您已经保护了应用程序的所有表单或敏感区域,现在的关键是使用您的视图模板来定义您的安全和公共(非 https)链接。
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/loginand http://yourhost/aboutus
这样做是呈现一个完全合格的 URL,例如https://yourhost/login和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.
如果您没有使用 http 呈现完全限定的 URL 并使用相对链接 url('/aboutus') 那么 https 将在用户访问安全站点后持续存在。
Hope this helps!
希望这可以帮助!
回答by Maulik Gangani
What about just using .htaccessfile 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.
仅使用.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/ [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.
我将它用于 laravel 5.4(撰写此答案时的最新版本),但即使 laravel 更改或删除某些功能,它也应继续适用于功能版本。
回答by Quy Le
回答by Artur Qaramyan
in IndexController.php put
在 IndexController.php 中放入
public function getIndex(Request $request)
{
if ($request->server('HTTP_X_FORWARDED_PROTO') == 'http') {
return redirect('/');
}
return view('index');
}
in AppServiceProvider.php put
在 AppServiceProvider.php 中放入
public function boot()
{
\URL::forceSchema('https');
}
}
In AppServiceProvider.php every redirect will be go to url https and for http request we need once redirect so in IndexController.php Just we need do once redirect
在 AppServiceProvider.php 中,每次重定向都会转到 url https,对于 http 请求,我们需要一次重定向,因此在 IndexController.php 中只需要进行一次重定向
回答by Phil
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/
上面的答案对我不起作用,但似乎 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]