在 Laravel 中使用 https 加载 Blade 资产

Load Blade assets with https in Laravel

我正在使用这种格式加载我的 css: <link href="{{ asset('assets/mdi/css/materialdesignicons.min.css') }}" media="all" rel="stylesheet" type="text/css" /> 它可以很好地加载所有 http 请求

但是当我使用 SSL (https) 加载我的登录页面时,我得到一个 ...page... was loaded over HTTPS, but requested an insecure stylesheet 'http...

有人可以告诉我如何 blade 通过 https 而不是 http 加载资产吗?

我应该尝试安全地加载资产吗?或者这不是Blade的工作?

我相信 secure_asset 就是您要找的。

<link href="{{ secure_asset('assets/mdi/css/materialdesignicons.min.css') }}" media="all" rel="stylesheet" type="text/css" />

5/15/2018 编辑: 虽然我的回答直接解决了这个问题,但考虑到 Laravel 现在可以做的事情,它有点过时了;在某些情况下,您可能希望在某些环境中强制使用 HTTPS,但在其他环境中不强制使用。

以获得更灵活的解决方案来应对此类情况。

08/11/2020 编辑: 说真的,伙计们, 比我的好,将为不同的环境提供更多的灵活性。给他你的建议。

另一种方法是将 true 作为第二个参数传递。

/**
 * Generate an asset path for the application.
 *
 * @param  string  $path
 * @param  bool    $secure
 * @return string
 */
function asset($path, $secure = null)
{
    return app('url')->asset($path, $secure);
}

如下所示,secure_asset 只需使用第二个参数 true 调用 asset

/**
 * Generate an asset path for the application.
 *
 * @param  string  $path
 * @return string
 */
function secure_asset($path)
{
    return asset($path, true);
}

我在网站使用 HTTPS 时通过 HTTP 协议加载资源时 asset 函数出现问题,这是导致 "Mixed content" 问题的原因。

要解决此问题,您需要将 \URL::forceScheme('https') 添加到 AppServiceProvider 文件中。

所以我的看起来像这样 (Laravel 5.4):

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if(config('app.env') === 'production') {
            \URL::forceScheme('https');
        }
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

当您仅在服务器 (config('app.env') === 'production') 而不是本地需要 https 时,这很有用,因此无需强制 asset 函数使用 https。

这是我的配置,可以使 HTTPS 与资产一起工作。要在生产中启用此功能,请在 .env 文件中添加 REDIRECT_HTTPS=true。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if(env('REDIRECT_HTTPS'))
        {
            \URL::forceScheme('https');
        }

        Schema::defaultStringLength(191);
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

我使用@Scofield 的回答 \URL::forceScheme('https'); 这个解决方案也可以为所有路由显示 https 但是这对我来说对 $request->url() 不起作用它显示 http 而不是 https

所以我用了$this->app['request']->server->set('HTTPS', true);而不是\URL::forceScheme('https');

我正在使用 Laravel 5.4 并更新 .env 文件和 appserviceproviders

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
use Log;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     *
     */
    public function boot()
    {
        If (env('APP_ENV') !== 'local') {
            $this->app['request']->server->set('HTTPS', true);
        }

        Schema::defaultStringLength(191);
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

在我的 env 文件中我已经更改了

APP_ENV=local to APP_ENV=development

APP_ENV=本地主机 APP_ENV=development/production 工作服务器

更改环境后 运行 这个 artisan 命令

php artisan config:clear

希望对您有所帮助:-)

判断当前 Request 是否安全不应该由您决定。底层 Symfony\Component\HttpFoundation\RequestisSecure 方法 Laravel 在内部使用。

public function isSecure()
{
    if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) {
        return \in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true);
    }

    $https = $this->server->get('HTTPS');

    return !empty($https) && 'off' !== strtolower($https);
}

因此,如果您的服务器没有通过 HTTPS header 和 On,它应该通过 X-FORWARDED-PROTO 并且必须得到您的 TrustProxies 的允许中间件。

如果你落后于 reverse-proxy,你应该找出你的代理传递 IP - 你可以通过获取 $_SERVER['REMOTE_ADDR'] 变量并将 IP 设置到你的 TrustProxies 中间件来轻松地做到这一点:

/**
 * The trusted proxies for this application.
 *
 * @var array
 */
protected $proxies = [
    '123.123.123.123',
];

Laravel (Symfony) 然后会自动检测 Request 是否安全并相应地选择协议。

问题是我本地机器上的 cloudflare 工作正常但在线服务器不是解决方案

 public function boot()
    {

        if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&  $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
             \URL::forceScheme('https');
        }
    }

我最终将其放入我的 blade 文件中:

@if(parse_url(url('/'), PHP_URL_SCHEME) == 'HTTPS')
    <link rel="stylesheet" href="{{ secure_asset('assets/css/slider.css') }}">
    <link rel="stylesheet" href="{{ secure_asset('assets/css/dropdown.css') }}">
@else
    <link rel="stylesheet" href="{{ asset('assets/css/slider.css') }}">
    <link rel="stylesheet" href="{{ asset('assets/css/dropdown.css') }}">
@endif

将 Laravel 版本从 5.4 升级到 5.5 时,我遇到了同样的问题。

只需在 app/Providers/AppServiceProvider.php 中添加 \URL::forceScheme('https');。成功了。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     *
     */
    public function boot()
    {
        \URL::forceScheme('https');
    }
...

有一个环境变量“ASSET_URL”,您可以将您的应用 url 与 http 或 https

放在一起
ASSET_URL=https://your.app.url #for production

ASSET_URL=http://your.app.url #for local development

在 .env 文件中请将本地值更改为生产环境

APP_ENV=production

而不是 "{{ asset('assets/mdi/css/materialdesignicons.min.css') }}" 使用 "{{ secure_asset('assets/mdi/css/materialdesignicons.min.css') }}"