在 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\Request
有 isSecure
方法 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') }}"
我正在使用这种格式加载我的 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\Request
有 isSecure
方法 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') }}"