在 Laravel 使用 https 加载 Blade 资产

我加载我的 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...

有没有人能告诉我如何通过 https 而不是 http 加载刀片服务器资源?

我应该试着安全地装载资产吗? 还是这不是 Blade 的工作?

108278 次浏览

I believe secure_asset is what you're looking for.

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

5/15/2018 Edit: While my answer addresses the question directly, it's a bit dated given what Laravel can do nowadays; there may be cases where you want to force HTTPS on certain environments but not on others.

See Scofield's answer below for a more flexible solution to cover for these kinds of cases.

08/11/2020 Edit: Seriously guys, Scofield's Answer is better than mine and will provide more flexibility for differing environments. Give him your updoots.

An another approach would be to pass true as the second parameter.

/**
* 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);
}

As you see below secure_asset simply calls asset with the second parameter true.

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

I had a problem with asset function when it's loaded resources through HTTP protocol when the website was using HTTPS, which is caused the "Mixed content" problem.

To fix that you need to add \URL::forceScheme('https') into your AppServiceProvider file.

So mine looks like this (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()
{
//
}
}

This is helpful when you need https only on server (config('app.env') === 'production') and not locally, so don't need to force asset function to use https.

Here is my configuration to make HTTPS working with assets. To enable this in production add REDIRECT_HTTPS=true in the .env file.

<?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()
{
//
}
}

I use @Scofield answer by use \URL::forceScheme('https'); This solution also worked to show https for all routes but this not worked for me for $request->url() it show http instead of https

so I used $this->app['request']->server->set('HTTPS', true); instead of \URL::forceScheme('https');

I'm using Laravel 5.4 and update .env file and 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()
{
//
}
}

in my env file I've changed

APP_ENV=local to APP_ENV=development

APP_ENV=local for localhost APP_ENV=development/production for on working server

after changing env run this artisan command

php artisan config:clear

Hope It helps :-)

Figuring out if the current Request is secure or not should not be your decision. Underlying Symfony\Component\HttpFoundation\Request has isSecure method that Laravel uses internally.

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);
}

So if your server is not passing the HTTPS header with On, it should be passing X-FORWARDED-PROTO and must be allowed by your TrustProxies middleware.

If you are behind reverse-proxy you should find out your proxy pass IP - you can do this easily by getting the $_SERVER['REMOTE_ADDR'] variable and setting the IP to your TrustProxies middleware:

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

Laravel (Symfony) will then automatically detect if the Request is secure or not and choose the protocol accordingly.

The problem is cloudflare on my local machines is working fine but online server not solution is

 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');
}
}

I ended up putting this in my blade file:

@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

While upgrading Laravel version from 5.4 to 5.5, I had the same issue.

Just add \URL::forceScheme('https'); in app/Providers/AppServiceProvider.php. It worked.

<?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');
}
...

There is a environment variable "ASSET_URL" where you put your app url with the http or https

ASSET_URL=https://your.app.url #for production

or

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

in .env file please change the value local to production

APP_ENV=production

Instead of "\{\{ asset('assets/mdi/css/materialdesignicons.min.css') }}" use "\{\{ secure_asset('assets/mdi/css/materialdesignicons.min.css') }}"