修改
我无法真正找到一种从路线名称生成安全网址的方法。
要获得完整的网址,请使用
echo route('my_route_name');
但该怎么办,如果我想要一个带https的网址?
答案 0 :(得分:56)
更新:正如评论中所指出的,更简单的方法是在4.2-5.3之间为Laravel版本添加URL::forceSchema('https');
或在版本5.4+中添加URL::forceScheme('https');
在boot
文件的AppServiceProvider
方法中。
旧回答:
它实际上是完全可能的,并且只需要一行代码即可完成。
Laravel本身并不检查SSL的存在,它取决于Symfony。我们的关键是让它相信当前的要求是安全的。
问题是,我们必须将HTTPS
server param
设置为true,最简单的方法是将以下代码粘贴到boot
的{{1}}方法中:
AppServiceProvider
在我的情况下,我只需要在生产中强制使用SSL,本地环境应该仍然适用于http。这就是我仅在生产时强制使用SSL的方法:
$this->app['request']->server->set('HTTPS', true);
顺便说一下,请注意这些术语,将来可能需要它们。
答案 1 :(得分:7)
事实证明,laravel并不关心url是否安全,因为它基于当前url生成。如果您在https页面上,route()
将返回安全网址。如果是http,那么http://
url
问题是,Laravel没有检测到https已启用,这是由于服务器配置错误造成的。
您可以通过调用Request::isSecure();
答案 2 :(得分:6)
我认为只有一种方法可以做到这一点。
要生成指定路由的安全URL,您可能希望将路由传递到secure_url
帮助程序函数。
secure_url(URL::route('your_route_name', [], false));
您无法真正使用route
辅助函数,因为它默认生成绝对网址(http://
),而http
不是{{1}您想要的版本
答案 3 :(得分:6)
如果检测到传入连接是安全的,Laravel 5.x将通过route()帮助程序生成安全URL。如果应用程序隐藏在负载均衡器或代理(例如Cloudflare)后面,通常会发生问题,因为应用服务器和负载均衡器/代理之间的连接可能不安全。
我现在正在使用Laravel Forge + Cloudflare,这是我能找到的最简单的方法,可以让app认为传入连接是安全的(不确定其他代理)。
生成自签名证书(请参阅https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs或http://www.selfsignedcertificate.com/)
在Forge面板中,通过Sites > your-site > SSL Certificates > Install Existing Certificate
插入您的私钥和证书。
激活
在CloudFlare面板Crypto > SSL
中,选择“完整”(不严格)
简而言之,客户端和Cloudflare之间的连接由Cloudflare自己的SSL保护。应用服务器和Cloudflare之间的连接受到您生成的证书的保护(因此应用程序看到'连接'是安全的。
您可以将相同的原则应用于其他堆栈。
答案 4 :(得分:5)
Laravel 8
我最近通过修改这个文件解决了这个问题:
app/Providers/AppServiceProvider.php
在方法 boot()
中添加以下内容:
URL::forceScheme('https');
在顶部添加使用:
use Illuminate\Support\Facades\URL;
要在您的本地环境中工作,您可以像这样离开:
public function boot()
{
if(env('APP_ENV') !== 'local') {
URL::forceScheme('https');
}
}
注意:不要忘记为生产文件设置环境变量 APP_ENV
和 prod
。
APP_ENV=prod
答案 5 :(得分:4)
正如我在relevant question中提到的那样,我找到了5种生成安全URL的方法。
配置Web服务器以将所有非安全请求重定向到https。 Nginx配置示例:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
使用https:
设置环境变量APP_URL
APP_URL=https://example.com
使用助手secure_url()(Laravel5.6)
将以下字符串添加到AppServiceProvider :: boot()方法(对于5.4+版本):
\Illuminate\Support\Facades\URL::forceScheme('https');
为路由组(Laravel5.6)隐式设置方案:
Route::group(['scheme' => 'https'], function () {
// Route::get(...)->name(...);
});
此方法目前尚无记录,但效果很好。
答案 6 :(得分:3)
使用secure_url:
secure_url(URL::route('your_route_name', [], false));
您需要将URL :: route设置为false才能返回完整的URL。然后使用secure_url函数为给定路径生成完全限定的HTTPS URL。
在UrlGenerator界面中,您可以使用URL :: route
string route(string $name, mixed $parameters = array(), bool $absolute = true)
Get the URL to a named route.
Parameters
string $name
mixed $parameters
bool $absolute
Return Value
string
https://laravel.com/api/5.4/Illuminate/Contracts/Routing/UrlGenerator.html
答案 7 :(得分:3)
在大多数情况下,应使用您的网站加载的相同方案生成路线。 Laravel会自动检测请求是否具有X-Forwarded-Proto
标头,并使用它来决定在生成的路由URL中使用哪种方案。如果您的站点位于反向代理之后,则应将反向代理IP地址添加到可信代理列表中。 https://github.com/fideloper/TrustedProxy包有助于实现此目的。在Laravel 5.5中它是included。例如,我的config/trustedproxy.php
看起来像:
<?php
return [
'proxies' => '*',
'headers' => [
]
];
我将它与具有以下配置的nginx反向代理一起使用:
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/example.com_access.log;
error_log /var/log/nginx/example.com_error.log;
client_max_body_size 50m;
location / {
proxy_pass http://localhost:8002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
将example.com
替换为您的域名。 SSL证书由Let's Encrypt certbot提供。
答案 8 :(得分:2)
在laravel 5.5上* 您只需要在.env文件上添加https 因为AppServiceProvider已经具有检查您配置上的APP_URL或app.url是否具有https的功能。
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
\URL::forceRootUrl(\Config::get('app.url'));
if (str_contains(\Config::get('app.url'), 'https://')) {
\URL::forceScheme('https');
}
}
答案 9 :(得分:1)
只需在 .env 文件的 APP_URL 中使用 https
协议添加您的应用程序域。
APP_URL=https://example.com
然后运行 route:cache
答案 10 :(得分:1)
这肯定是古老的,但是有一天像我这样的人会在这里倾倒。
在您的.env文件中,定义APP_URL以使用https而不使用http。因为所有的laravel网址都是基于此变量生成的。
APP_URL=https://example.com
以及您想说的任何地方
{{ URL::route('my.route', params) }}
或
{{ route('my.route', params) }}
确保所有路由均使用安全协议生成,然后添加AppServiceProvider类的启动方法:
<?php
namespace App\Providers;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(UrlGenerator $url)
{
if (config('app.production')) {
$url->forceScheme('https');
}
}
答案 11 :(得分:0)
我尝试使用Laravel 5.4在Blade中生成路径作为表单操作时遇到此问题。 然后我点击了secure_url(),所以我尝试了
{{ secure_url(route('routename', $args)) }}
这仍然返回了一个非安全的URL。 : - (
在深入研究代码并添加一些调试日志后,我终于发现secure_url不会更改传入的url参数,如果它已经是绝对URL(包括方案)。
幸运的是,route有一个绝对标志作为第三个参数,如果$ absolute被传递为false,则返回一个相对URL。
假设/ a / {id} / b是命名路线&#34; a.b&#34;
route('a.b', 1) : will return http://[domain]/a/1/b
route('a.b', 1, false) : will return /a/1/b
加入我到达的那两个:
{{ secure_url(route('routename', $args, false)) }}
正如预期的那样,它生成了https://[domain]/routeXXX
: - )
答案 12 :(得分:0)
寻找错误2小时后,重定向尾部的斜杠出现了问题,只需删除
.htaccess
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
到
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
答案 13 :(得分:0)
供将来访客参考:
secure_url函数无法正确处理GET参数。因此,例如,如果您要将用户访问过的网址转换为安全网址,同时保留GET字段,则需要使用以下命令:
secure_url(Request::path()).'?'.http_build_query(Input::all());
特别注意使用path()而不是url() - 如果你给它一个完整的url,它不会在开始时替换http,使它有效无用。
答案 14 :(得分:-1)
根据laravel文档中的 url()帮助器方法。
如果未提供路径,则为 Illuminate \ Routing \ UrlGenerator 实例 返回
因此,您可以通过以下方式使用 UrlGenerator 类的安全方法:
echo url()->secure('my_route_name');
答案 15 :(得分:-2)
将它放在您的filters.php文件中,并且在保留URL参数的同时将强制要求https:
//force ssl
App::before(function () {
if(!Request::secure() && App::environment() != 'local')
{
$baseHost = Request::getHttpHost();
$requestUri = Request::getRequestUri();
$newLink = 'https://'.$baseHost.$requestUri;
return Redirect::to($newLink);
}});
答案 16 :(得分:-5)
要生成安全(https)路由,请使用以下内置&#39;之前&#39;过滤器名为&#39; auth&#39;:
例如:
Route::get('your-route', ['before' => 'auth', 'uses' => YourController@yourAction']);
现在,当您输出链接时,它将以&#39; https&#39;
为前缀