我们的整个网站都将通过https提供服务。我在每条路线都有'https'。但是,如果他们通过http?
尝试将其重定向到https?Route::group(array('https'), function()
{
// all of our routes
}
答案 0 :(得分:94)
使用App ::之前
您可以利用App::before()
文件中的app/filters.php
块。
更改块以包含一个简单的检查以查看当前请求是否安全,如果不安全,则重定向。
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
使用过滤器
另一种选择可能是创建一个这样的过滤器。人们通常也将其存储在app/filters.php
。
Route::filter('force.ssl', function()
{
if( ! Request::secure())
{
return Redirect::secure(Request::path());
}
});
然后,您可以对您的任何路线,路线组或控制器强制执行新的过滤器。
个人路线
Route::get('something', ['before' => 'force.ssl'], function()
{
return "This will be forced SSL";
});
路线组
Route::group(['before' => 'force.ssl'], function()
{
// Routes here.
});
控制器的
您需要在控制器的__construct()
方法中执行此操作。
public function __construct()
{
$this->beforeFilter('force.ssl');
}
答案 1 :(得分:33)
另一个答案可能是让您的Web服务器处理此问题。如果您使用的是Apache,则可以使用RedirectSSL功能确保所有请求都转到您站点的HTTPS版本,如果没有重定向它们。这将在Laravel得到请求之前发生。
如果您使用的是NGINX,则可以通过使用两个服务器块来实现此目的。一个用于端口80上的普通HTTPS,另一个用于端口443上的HTTPS。然后将普通服务器块配置为始终重定向到ssl版本。
server {
listen 80;
server_name mydomain.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443;
server_name mydomain.com;
ssl on;
# other server config stuff here.
}
我亲自使用此选项,因为PHP本身并不需要处理任何事情。在Web服务器级别处理这样的支票通常会更便宜。
答案 2 :(得分:12)
对于使用Laravel 4/5和Elastic Beanstalk的用户,使用这些方法强制HTTPS很困难,因为isSecure()
将返回false
。此外,使用.htaccess
重定向会导致Chrome的重定向循环以及Firefox中延迟的页面加载时间。
此设置适用于
aws
。 Linux可能略有不同?经过几个小时的尝试后,我设法使用以下步骤将所有HTTP请求转发到HTTPS:
获取SSL证书。指南和提供商众多,可通过Google搜索找到。
使用aws
控制台命令将证书上传到AWS。命令结构是:
aws iam upload-server-certificate --server-certificate-name CERTIFICATE_NAME --certificate-body "file://PATH_TO_CERTIFICATE.crt" --private-key "file://YOUR_PRIVATE_KEY.pem" --certificate-chain "file://YOUR_CERTIFICATE_CHAIN.ca-bundle" --path /cloudfront/
创建Elastic Beanstalk应用程序。继续完成设置过程。设置应用程序后,转到配置 - > 网络层 - > 加载平衡,然后点击齿轮图标。
选择安全侦听器端口为 443 。选择协议为 HTTPS 。为 SSL证书ID 从第2步中选择CERTIFICATE_NAME
。保存配置。
转到控制台。点击 EC2实例。点击加载平衡器。单击负载平衡器。单击实例,然后向下滚动以查看分配给该负载均衡器的EC2实例。如果EC2实例与您的应用程序URL具有相同的名称(或关闭的内容),请记下负载均衡器的 DNS名称。它应采用awseb-e-...
返回控制台。点击 CloudFront 。点击创建分配。选择网络分发。
设置分发。将原始域名设置为您在步骤5 中找到的负载均衡器DNS名称。将查看器协议策略设置为将HTTP重定向到HTTPS 。将转发查询字符串设置为是。将备用域名(CNAME)设置为您要用于应用程序的URL。将 SSL证书设置为您在第2步中上传的CERTIFICATE_NAME
。创建您的发行版。
在CloudFront中单击您的分发名称。点击来源,选择您的来源,然后点击修改。确保原始协议政策 匹配查看器。回去。点击行为,选择您的来源,然后点击修改。将转发标题更改为白名单,然后添加主机。保存。
转到控制台。点击路线53 。点击托管区域。点击创建托管区域。设置您的域名。设置完成后,单击创建记录集。输入您的A记录。选择别名为是。您的别名目标是您的CloudFront分配。保存记录。
为您的域设置名称服务器以指向Route 53名称服务器。等待一切传播,这可能是几个小时。转到您的网址。您将自动重定向到HTTPS。
“但是等等,我的链接不会转到HTTPS!?”您需要处理CloudFront将传递的X-Forwarded-Proto
标头。对于Laravel 4,follow this guide。对于Laravel 5,运行:
php artisan make:middleware EB_SSL_Trust
然后将其添加到EB_SSL_Trust
文件中:
public function handle($request, Closure $next)
{
$request->setTrustedProxies( [ $request->getClientIp() ] );
return $next($request);
}
并将其添加到您的App\Http\Kernel.php
文件中:
protected $middleware = [
...
'App\Http\Middleware\EB_SSL_Trust',
...
];
注意:您的所有资产(例如CSS,JS或图片)都需要通过HTTPS发送。如果您使用Laravel创建这些链接,请使用secure_asset()
在您的视图中创建HTTPS网址。
答案 3 :(得分:8)
Laravel 5.1。* 中不推荐使用过滤器。这对于MiddleWare来说是一个完美的工作。
创建一个中间件并在句柄部分输入
public function handle($request, Closure $next)
{
if(! $request->secure()) {
return redirect()->secure($request->path());
}
return $next($request);
}
然后只需在Kernel.php中注册中间件,并将其与路由或控制器一起使用。
答案 4 :(得分:7)
使用.htaccess Apache进行laravel 4.2.X
原始文件
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
编辑文件/public/.htaccess
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes...
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
答案 5 :(得分:5)
结合以前的答案并更新Laravel 4.2:
Route::filter('secure', function () {
if (! Request::secure()) {
return Redirect::secure(
Request::path(),
in_array(Request::getMethod(), ['POST', 'PUT', 'DELETE']) ? 307 : 302
);
}
});
Route::when('*', 'secure');
答案 6 :(得分:3)
如果您想使用https重定向到同一网址,则应使用Request::getRequestUri()
代替Request::path()
:
App::before(function($request)
{
if( ! Request::secure())
{
return Redirect::secure(Request::getRequestUri());
}
});
答案 7 :(得分:2)
这在Apache 2.4中适用于我
我在Laravel的根文件夹中更改了.htaccess
从
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
要
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
答案 8 :(得分:1)
如果您遇到问题,由于某些原因Request::secure()
返回false,即使网址为https
,也可能是因为$ _SERVER ['HTTPS']值不存在。< / p>
这是一种解决方法:
App::before(function ($request){
// Force https
if(!Request::secure() && array_get($_SERVER, 'SERVER_PORT') != 443){
return Redirect::secure(Request::path());
}
});
答案 9 :(得分:1)
我在执行POST请求时强制执行ssl有问题。它总是会重定向到GET。发生这种情况是因为Redirect::secure()
默认使用302重定向。
要确保正确重定向POST请求,请使用
之类的内容return Redirect::secure("your/path/here", 307)
这将确保您的请求在重定向发生后将保留原始请求方法。
答案 10 :(得分:1)
我不详细了解HTTP和HTTPS,所以如果这个答案不是很好,我很抱歉。
我的理解是存在一个问题,即使客户端和(客户端指定的)服务器使用HTTPS,Request::secure()
也可能返回false,因为您的应用程序可能正在另一台服务器上运行,该服务器可能没有接收到https请求。
我正在heroku中托管我的laravel应用程序,它似乎就是这样。我的 猜测 是主要(客户端指定的)服务器是负载均衡器,当转发请求时,它作为普通的HTTP请求到达另一台服务器。
如果发生此类转发,您不应只检查Request::secure()
是否为true
。我被#laravel @ irc.freenode.com的某人指示也检查Request::server('HTTP_X_FORWARDED_PROTO')
以查看它是否等于'https'
。
因此,如果您打算在此处遵循其他建议并在非安全的情况下执行重定向,请尝试检查此服务器参数。
答案 11 :(得分:1)
对于laravel 5.1,您应该使用App\Http\Providers\RouteServiceProvider@boot
$router->filter('force.ssl', function () {
if ( ! request()->secure() ) {
return redirect()->secure(request()->path());
}
});
现在您可以在路线文件中使用它。
Route::group(['before' => 'force.ssl'], function () {
// Routes here
});
您还可以在['before' => 'force.ssl']
$router->group()
App\Http\Providers\RouteServiceProvider@map
答案 12 :(得分:0)
如果在代理后面并且Request :: secure()不起作用。
App::before( function( $request )
{
// set the current IP (REMOTE_ADDR) as a trusted proxy
Request::setTrustedProxies( [ $request->getClientIp() ] );
});
答案 13 :(得分:0)
结合以前的答案,使用Laravel 4.2中提供的常量和方法。
<强> routes.php文件强>
Route::when('*', 'secure');
<强> filters.php 强>
use Illuminate\Http\Response as IlluminateResponse;
Route::filter('secure', function ()
{
if ( ! Request::secure() && Request::getPort() != 443)
{
return Redirect::secure(
Request::path(),
in_array(Request::getMethod(), ['POST', 'PUT', 'DELETE'])
? IlluminateResponse::HTTP_TEMPORARY_REDIRECT
: IlluminateResponse::HTTP_FOUND
);
}
});
答案 14 :(得分:0)
如果您必须使用Laravel 4本身来处理重定向(像我一样),我会进行以下设置(解释为代码中的注释):
路线过滤器:
// app/filters.php
Route::filter('ssl.force', function()
{
if(App::environment('production') && !Request::secure())
{
// don't set a session cookie when redirecting to another scheme to
// avoid dropping the session when switching scheme
Config::set('session.driver', 'array');
// preserve query string while redirecting by using fullUrl()
// instead of Redirect::secure + Request::path()
$url = str_replace('http://', 'https://', Request::fullUrl());
return Redirect::to($url, 302, array(), true);
}
// secure cookies for https
Config::set('session.secure', Request::secure());
});
然后将过滤器作为前置过滤器应用于路径或路径组。 例如:
// app/routes.php
Route::group(array('before' => 'ssl.force'), function () {
// SSL routes
});