Laravel从路由生成安全的https URL

时间:2014-06-26 09:01:45

标签: url laravel https routing

修改

我无法真正找到一种从路线名称生成安全网址的方法。

要获得完整的网址,请使用

echo route('my_route_name');

但该怎么办,如果我想要一个带https的网址?

17 个答案:

答案 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();

来检查Laravel是否将当前连接视为https

答案 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认为传入连接是安全的(不确定其他代理)。

  1. 生成自签名证书(请参阅https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrshttp://www.selfsignedcertificate.com/

  2. 在Forge面板中,通过Sites > your-site > SSL Certificates > Install Existing Certificate插入您的私钥和证书。

  3. 激活

  4. 在CloudFlare面板Crypto > SSL中,选择“完整”(不严格)

  5. 完成(改变传播需要几分钟)
  6. 简而言之,客户端和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_ENVprod

APP_ENV=prod

答案 5 :(得分:4)

正如我在relevant question中提到的那样,我找到了5种生成安全URL的方法。

  1. 配置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;
    }
    
  2. 使用https:

    设置环境变量APP_URL
    APP_URL=https://example.com
    
  3. 使用助手secure_url()(Laravel5.6)

  4. 将以下字符串添加到AppServiceProvider :: boot()方法(对于5.4+版本):

    \Illuminate\Support\Facades\URL::forceScheme('https');
    
  5. 为路由组(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;

为前缀