Laravel 5 - 重定向到 HTTPS
Laravel 5 - redirect to HTTPS
正在处理我的第一个 Laravel 5 项目,不确定在何处或如何放置逻辑以在我的应用程序上强制使用 HTTPS。这里的关键是有许多域指向该应用程序,并且只有三分之二的域使用 SSL(第三个是后备域,长话短说)。所以我想在我的应用程序的逻辑中处理这个而不是 .htaccess。
在 Laravel 4.2 中,我使用位于 filters.php
:
中的代码完成了重定向
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
我在想中间件是应该实现这样的东西的地方,但我不太明白如何使用它。
谢谢!
更新
如果您像我一样使用 Cloudflare,可以通过在控制面板中添加新的 Page Rule 来实现。
您可以让它与中间件一起工作 class。让我给你一个想法。
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:
- 当前请求没有安全协议 (http)
- 如果你的环境等于
production
。因此,只需根据您的喜好调整设置即可。
Cloudflare
我在带有 WildCard SSL 的生产环境中使用此代码并且代码工作正常。如果我删除 && App::environment() === 'production'
并在本地主机中对其进行测试,则重定向也有效。因此,是否安装 SSL 不是问题。看起来您需要非常注意 Cloudflare 层才能重定向到 Https 协议。
编辑 23/03/2015
感谢@Adam Link
的建议:可能是Cloudflare经过的header造成的。 CloudFlare 可能通过 HTTP 访问您的服务器并传递 X-Forwarded-Proto header 声明它正在转发 HTTPS 请求。你需要在你的中间件中添加另一行说...
$request->setTrustedProxies( [ $request->getClientIp() ] );
...相信 headers CloudFlare 正在发送。这将停止重定向循环
编辑 27/09/2016 - Laravel v5.3
只需要将中间件class添加到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
],
];
Remember that web
group is applied to every route by default, so you do not need to set web
explicitly in routes nor controllers.
编辑 23/08/2018 - Laravel v5.7
- 要根据环境重定向请求,您可以使用
App::environment() === 'production'
。对于以前的版本是
env('APP_ENV') === 'production'
.
- 使用
\URL::forceScheme('https');
实际上并没有重定向。它只是在网站呈现后与 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()],
Request::HEADER_X_FORWARDED_ALL);
if (!$request->isSecure()) {
return redirect()->secure($request->getRequestUri());
}
}
return $next($request);
}
}
这适用于 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,
];
接下来,我想保护两个基本组 login/signup 等以及 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
现在您已经保护了应用程序的所有表单或敏感区域,现在的关键是使用您的视图模板来定义您的安全和 public(非 https)link。
根据上面的示例,您将按如下方式呈现您的安全 links -
<a href="{{secure_url('/login')}}">Login</a>
<a href="{{secure_url('/signup')}}">SignUp</a>
非安全 link 可以呈现为
<a href="{{url('/aboutus',[],false)}}">About US</a></li>
<a href="{{url('/promotion',[],false)}}">Get the deal now!</a></li>
它所做的是呈现完全限定的 URL,例如 https://yourhost/login and http://yourhost/aboutus
如果您没有使用 http 呈现完全合格的 URL 并使用相对 link url('/aboutus') 那么 https 将在用户访问安全站点后持续存在.
希望对您有所帮助!
另一个对我有用的选项,在 AppServiceProvider 中将这段代码放在引导方法中:
\URL::forceScheme('https');
forceSchema('https')之前写的函数错了,它的forceScheme
在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 我们只需要做一次重定向
只用.htaccess文件实现https重定向怎么样?这应该放在项目根目录中(而不是 public 文件夹中)。您的服务器需要配置为指向项目根目录。
<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>
我将它用于 laravel 5.4(撰写此答案时的最新版本),但即使 laravel 更改或删除某些功能,它也应该继续用于功能版本。
或者,如果您使用的是 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 使用此格式获取 https 重定向而不是 .htaccess
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
}
}
上面的答案对我不起作用,但 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]
这是在 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
这会将 header X-forwarded 设置为它将在 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 不会被设置(我们用上面的 curl 伪造它以查看发生了什么)。
对于 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());
}
您可以使用 RewriteRule 在与您 index.php 相同的文件夹中强制 .htaccess 中的 ssl
请添加为图片附件,将其添加在所有规则其他之前
这对我很有效。
我制作了自定义 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 } ?>
如果您使用的是 CloudFlare,则只需创建一个 Page Rule 以始终使用 HTTPS:
这会将每个 http:// 请求重定向到 https://
除此之外,您还必须在 \app\Providers\AppServiceProvider.php boot() 函数中添加类似的内容:
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
这将确保您应用中的每个 link / 路径都使用 https:// 而不是 http://。
我正在添加这个替代方案,因为我在这个问题上受了很多苦。我尝试了所有不同的方法,但没有任何效果。所以,我想出了一个解决方法。它可能不是最好的解决方案,但它确实有效 -
FYI, I am using Laravel 5.6
if (App::environment('production')) {
URL::forceScheme('https');
}
production <- 它应该替换为 .env 文件中的 APP_ENV 值
我正在 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);
}
}
最简单的方法是在应用程序级别。在文件中
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 测试)
略有不同的方法,已在 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 的评论更新。
这对我有用 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
内核文件
中注册中间件
内核
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/ [R,L]
</IfModule>
此致!
您可以简单地转到 app -> Providers -> 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.
}
在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
使用 Laravel 重定向到 HTTPS 的最简单方法是使用 .htaccess
所以你所要做的就是将以下行添加到你的 .htaccess 文件中,你就可以开始了。
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
确保在 .htaccess 文件中找到的现有(*default)
代码之前添加它,否则 HTTPS 将无法工作。
这是因为现有(默认)代码已经处理了一个重定向,该重定向将所有流量重定向到主页,然后该路由根据您的 URL
接管
所以把代码放在前面意味着 .htaccess 将在路由接管之前首先将所有流量重定向到 https
我发现这对我有用。首先将此代码复制到 .htaccess
文件中。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
正在处理我的第一个 Laravel 5 项目,不确定在何处或如何放置逻辑以在我的应用程序上强制使用 HTTPS。这里的关键是有许多域指向该应用程序,并且只有三分之二的域使用 SSL(第三个是后备域,长话短说)。所以我想在我的应用程序的逻辑中处理这个而不是 .htaccess。
在 Laravel 4.2 中,我使用位于 filters.php
:
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
我在想中间件是应该实现这样的东西的地方,但我不太明白如何使用它。
谢谢!
更新
如果您像我一样使用 Cloudflare,可以通过在控制面板中添加新的 Page Rule 来实现。
您可以让它与中间件一起工作 class。让我给你一个想法。
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:
- 当前请求没有安全协议 (http)
- 如果你的环境等于
production
。因此,只需根据您的喜好调整设置即可。
Cloudflare
我在带有 WildCard SSL 的生产环境中使用此代码并且代码工作正常。如果我删除 && App::environment() === 'production'
并在本地主机中对其进行测试,则重定向也有效。因此,是否安装 SSL 不是问题。看起来您需要非常注意 Cloudflare 层才能重定向到 Https 协议。
编辑 23/03/2015
感谢@Adam Link
的建议:可能是Cloudflare经过的header造成的。 CloudFlare 可能通过 HTTP 访问您的服务器并传递 X-Forwarded-Proto header 声明它正在转发 HTTPS 请求。你需要在你的中间件中添加另一行说...
$request->setTrustedProxies( [ $request->getClientIp() ] );
...相信 headers CloudFlare 正在发送。这将停止重定向循环
编辑 27/09/2016 - Laravel v5.3
只需要将中间件class添加到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
],
];
Remember that
web
group is applied to every route by default, so you do not need to setweb
explicitly in routes nor controllers.
编辑 23/08/2018 - Laravel v5.7
- 要根据环境重定向请求,您可以使用
App::environment() === 'production'
。对于以前的版本是env('APP_ENV') === 'production'
. - 使用
\URL::forceScheme('https');
实际上并没有重定向。它只是在网站呈现后与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()],
Request::HEADER_X_FORWARDED_ALL);
if (!$request->isSecure()) {
return redirect()->secure($request->getRequestUri());
}
}
return $next($request);
}
}
这适用于 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,
];
接下来,我想保护两个基本组 login/signup 等以及 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
现在您已经保护了应用程序的所有表单或敏感区域,现在的关键是使用您的视图模板来定义您的安全和 public(非 https)link。
根据上面的示例,您将按如下方式呈现您的安全 links -
<a href="{{secure_url('/login')}}">Login</a>
<a href="{{secure_url('/signup')}}">SignUp</a>
非安全 link 可以呈现为
<a href="{{url('/aboutus',[],false)}}">About US</a></li>
<a href="{{url('/promotion',[],false)}}">Get the deal now!</a></li>
它所做的是呈现完全限定的 URL,例如 https://yourhost/login and http://yourhost/aboutus
如果您没有使用 http 呈现完全合格的 URL 并使用相对 link url('/aboutus') 那么 https 将在用户访问安全站点后持续存在.
希望对您有所帮助!
另一个对我有用的选项,在 AppServiceProvider 中将这段代码放在引导方法中:
\URL::forceScheme('https');
forceSchema('https')之前写的函数错了,它的forceScheme
在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 我们只需要做一次重定向
只用.htaccess文件实现https重定向怎么样?这应该放在项目根目录中(而不是 public 文件夹中)。您的服务器需要配置为指向项目根目录。
<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>
我将它用于 laravel 5.4(撰写此答案时的最新版本),但即使 laravel 更改或删除某些功能,它也应该继续用于功能版本。
或者,如果您使用的是 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 使用此格式获取 https 重定向而不是 .htaccess
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
}
}
上面的答案对我不起作用,但 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]
这是在 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
这会将 header X-forwarded 设置为它将在 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 不会被设置(我们用上面的 curl 伪造它以查看发生了什么)。
对于 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());
}
您可以使用 RewriteRule 在与您 index.php 相同的文件夹中强制 .htaccess 中的 ssl
请添加为图片附件,将其添加在所有规则其他之前
这对我很有效。 我制作了自定义 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 } ?>
如果您使用的是 CloudFlare,则只需创建一个 Page Rule 以始终使用 HTTPS:
除此之外,您还必须在 \app\Providers\AppServiceProvider.php boot() 函数中添加类似的内容:
if (env('APP_ENV') === 'production' || env('APP_ENV') === 'dev') {
\URL::forceScheme('https');
}
这将确保您应用中的每个 link / 路径都使用 https:// 而不是 http://。
我正在添加这个替代方案,因为我在这个问题上受了很多苦。我尝试了所有不同的方法,但没有任何效果。所以,我想出了一个解决方法。它可能不是最好的解决方案,但它确实有效 -
FYI, I am using Laravel 5.6
if (App::environment('production')) {
URL::forceScheme('https');
}
production <- 它应该替换为 .env 文件中的 APP_ENV 值
我正在 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);
}
}
最简单的方法是在应用程序级别。在文件中
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 测试)
略有不同的方法,已在 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 的评论更新。
这对我有用 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
内核文件
内核
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/ [R,L]
</IfModule>
此致!
您可以简单地转到 app -> Providers -> 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.
}
在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
使用 Laravel 重定向到 HTTPS 的最简单方法是使用 .htaccess
所以你所要做的就是将以下行添加到你的 .htaccess 文件中,你就可以开始了。
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
确保在 .htaccess 文件中找到的现有(*default)
代码之前添加它,否则 HTTPS 将无法工作。
这是因为现有(默认)代码已经处理了一个重定向,该重定向将所有流量重定向到主页,然后该路由根据您的 URL
所以把代码放在前面意味着 .htaccess 将在路由接管之前首先将所有流量重定向到 https
我发现这对我有用。首先将此代码复制到 .htaccess
文件中。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>