处理我的第一个Laravel 5项目,并且不确定在我的应用上强制使用HTTPS的逻辑位置或方式。这里的关键是有许多域指向应用程序,只有三分之二使用SSL(第三个是后备域,长篇故事)。所以我想在我的应用程序的逻辑中处理这个问题,而不是.htaccess。
在Laravel 4.2中,我使用此代码完成了重定向,位于filters.php
:
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
我认为中间件应该在这样的地方实现,但我无法用它来解决这个问题。
谢谢!
更新
如果您像我一样使用Cloudflare,可以通过在控制面板中添加新的页面规则来实现。
答案 0 :(得分:202)
您可以使其适用于中间件类。让我给你一个想法。
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不是问题。看起来你需要非常注意你的Cloudflare层,以便重定向到Https协议。
感谢@Adam Link
的建议:它可能是由Cloudflare传递的标头引起的。 CloudFlare可能通过HTTP命中您的服务器并传递X-Forwarded-Proto标头,声明它正在转发HTTPS请求。您需要在中间件中添加另一行说...
$request->setTrustedProxies( [ $request->getClientIp() ] );
...信任CloudFlare正在发送的标头。这将停止重定向循环
只需将中间件类添加到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
。
App::environment() === 'production'
。对于以前的版本是
env('APP_ENV') === 'production'
。\URL::forceScheme('https');
实际上不会重定向。它只是在呈现网站时与https://
建立链接。答案 1 :(得分:49)
另一个适用于我的选项,在AppServiceProvider中将此代码放在引导方法中:
\URL::forceScheme('https');
在forceScheme(' https')之前编写的函数错误,其forceScheme
答案 2 :(得分:23)
或者,如果您使用的是Apache,则可以使用.htaccess
文件强制您的URL使用https
前缀。在Laravel 5.4上,我在.htaccess
文件中添加了以下行,它对我有用。
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
答案 3 :(得分:13)
for 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');
}
}
答案 4 :(得分:10)
与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);
}
}
答案 5 :(得分:6)
这适用于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,因此不需要。
将以下内容添加到您的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>
这样做会呈现一个完全限定的网址,例如https://yourhost/login和http://yourhost/aboutus
如果您没有使用http呈现完全限定的网址并使用相对链接网址('/ aboutus'),则在用户访问安全网站后,https会一直存在。
希望这有帮助!
答案 6 :(得分:5)
答案 7 :(得分:5)
使用 .htaccess 文件实现https重定向怎么样?这应该放在项目根目录中(不在公用文件夹中)。您的服务器需要配置为指向项目根目录。
\root
\root\index.php
\root\load.php
我将此用于laravel 5.4(编写此答案时的最新版本),但即使laravel更改或删除某些功能,它仍应继续用于功能版本。
答案 8 :(得分:3)
上面的答案对我不起作用,但似乎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]
答案 9 :(得分:3)
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中我们需要做一次重定向
答案 10 :(得分:1)
以下是如何在Heroku上执行此操作
要在您的dynos上强制使用SSL而不是在本地强制使用SSL,请在公共/。
中添加.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-forward设置为将在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>
这是重定向。如果您将.htaccess设置为如上所述,那就是heroku将返回给客户端的内容。但它不会发生在您的本地计算机上,因为X-forwarded将不会被设置(我们用上面的卷曲伪造它以查看发生了什么)。
答案 11 :(得分: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());
}
答案 12 :(得分: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 } ?>
答案 13 :(得分:1)
如果您正在使用CloudFlare,则可以创建一个页面规则以始终使用HTTPS: 这会将每个http://请求重定向到https://
除此之外,您还必须在\ app \ Providers \ AppServiceProvider.php boot()函数中添加以下内容:
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
这将确保您应用中的每个链接/路径都使用https://而不是http://。
答案 14 :(得分:1)
我正在添加此替代方法,因为我在这个问题上受了很多苦。我尝试了所有不同的方式,但没有任何效果。因此,我想出了一种解决方法。它可能不是最好的解决方案,但确实有效-
仅供参考,我使用的是Laravel 5.6
if (App::environment('production')) {
URL::forceScheme('https');
}
生产<-应该用.env文件中的APP_ENV值替换
答案 15 :(得分:1)
我正在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);
}
}
答案 16 :(得分:1)
稍有不同的方法,已在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);
}
}
答案 17 :(得分:1)
您可以简单地转到 app -> 提供商-> 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.
}
答案 18 :(得分:1)
在Laravel 5.1中,我使用了: 文件: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;
}
注意:使用forceSchema
,而不是forceScheme
答案 19 :(得分:0)
最简单的方法是在应用程序级别。在文件
中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进行了测试)
答案 20 :(得分:0)
使用中间件通过 3个简单步骤在 Laravel 7.x 中为我工作:
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
中注册中间件
内核
protected $routeMiddleware = [
//...
'ssl' => \App\Http\Middleware\ForceSSL::class,
];
3)在您的路线中使用
路线
Route::middleware('ssl')->group(function() {
// All your routes here
});
此处是有关middlewares的完整文档
======================
.HTACCESS方法
如果您更喜欢使用.htaccess
文件,则可以使用以下代码:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://yourdomain.com/$1 [R,L]
</IfModule>
致谢!
答案 21 :(得分:0)
使用 Laravel 重定向到 HTTPS 的最简单方法是使用 .htaccess
所以你所要做的就是将以下几行添加到你的 .htaccess 文件中,你就可以开始了。
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
确保在 .htaccess 文件中找到的现有(*default)
代码之前添加它,否则 HTTPS 将无法工作。
这是因为现有(默认)代码已经处理重定向,将所有流量重定向到主页,然后路由根据您的 URL 接管
所以把代码放在第一位意味着.htaccess会在路由接管之前首先将所有流量重定向到https
答案 22 :(得分:0)
我发现这对我有用。首先将此代码复制到 .htaccess
文件中。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>