【PHP框架 | Laravel8 系列5】 - 视图与CSRF保护

7 篇文章 1 订阅

前言:之前在学习并使用 Laravel 框架过程中,全是碎片化掌握,现在重新学习并记录一次学习的过程。

本文内容对应 Laravel8.* 版本。


Laravel 直达入口:


一、视图

Laravel 的视图文件存放于 resources/views 目录中。

1.1 创建视图

<!-- View stored in resources/views/greeting.blade.php -->

<html>
    <body>
        <h1>Hello, {{ $name }}</h1>
    </body>
</html>

将上述代码保存至 resources/views/greeting.blade.php 文件后,就可以通过 view 助手函数返回。


view 助手函数的第一个参数为 视图模板的名称,第二个参数为可供视图的数据数组。


Route::get('/', function () {
    return view('greeting', ['name' => 'James']);
});

也可将模板保存至 views 的子目录。使用 点 . 引用嵌套视图。

return view('admin.profile', $data);

1.2 判断视图是否存在

use Illuminate\Support\Facades\View;

# 如果存在,则会返回 true
if (View::exists('emails.customer')) {
    //
}

1.3 向视图传递数据

  1. 使用 view 助手函数的第二个参数

  2. 使用 view 助手函数链式调用 with 方法

    return view('greeting')->with('name', 'Victoria');
    

1.4 与所有视图共享数据

有时,有一些公共数据需要在所有页面都展示,这时,你就可以在 服务提供器的 boot 方法中调用视图门面的 share 方法。例如

<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;

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

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        View::share('key', 'value');
    }
}

二、视图合成器

视图合成器是调用视图时的回调或者类方法。在视图即将渲染时执行


默认没有存放 视图合成器 的目录,例如可以新建并存放在 app/Http/View/Composers 目录中。


使用 View 门面调用 composer 方法,即可在视图渲染之前被调用。


2.1 创建视图合成器

接下来的示例步骤是:

  1. 创建服务提供者并注册
  2. 在服务提供者的 boot 方法中,调用 composer 方法,定义视图合成器
  3. 定义视图合成器调用类
  1. 创建服务提供者,并在 config/app.php 文件中的 providers 数组中注册

    <?php
    
    namespace App\Providers;
    
    use Illuminate\Support\Facades\View;
    use Illuminate\Support\ServiceProvider;
    
    class ViewServiceProvider extends ServiceProvider
    {
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            
            # 2. 在服务提供者的 `boot` 方法中,调用 `composer` 方法,定义视图合成器
            
            // Using class based composers...
            View::composer(
                'profile', 'App\Http\View\Composers\ProfileComposer'
            );
    
            // Using Closure based composers...
            View::composer('dashboard', function ($view) {
                //
            });
        }
    }
    
  2. 定义视图合成器调用类

    <?php
    
    namespace App\Http\View\Composers;
    
    use App\Repositories\UserRepository;
    use Illuminate\View\View;
    
    class ProfileComposer
    {
        /**
         * The user repository implementation.
         *
         * @var UserRepository
         */
        protected $users;
    
        /**
         * Create a new profile composer.
         *
         * @param  UserRepository  $users
         * @return void
         */
        public function __construct(UserRepository $users)
        {
            // Dependencies automatically resolved by service container...
            $this->users = $users;
        }
    
        /**
         * Bind data to the view.
         *
         * @param  View  $view
         * @return void
         */
        public function compose(View $view)
        {
            $view->with('count', $this->users->count());
        }
    }
    

所有的视图合成器都会通过 服务容器 进行解析,所以你可以在视图合成器的构造函数中类型提示需要注入的依赖项。


2.2 将视图合成器添加到多个视图

通过 composer 方法的第一个参数传入 视图数组,就可以将多个视图添加到视图合成器中。


通过 composer 方法的第一个参数传入 星号 *,就可以将所有视图添加到视图合成器中。

# 多个
View::composer(
    ['profile', 'dashboard'],
    'App\Http\View\Composers\MyViewComposer'
);

# 所有
View::composer('*', function ($view) {
    //
});

三、视图构造器

与视图合成器不同的是,视图构造器在 视图实例化之后执行。


其他使用方法与视图合成器相同。


使用 View 门面的 creator 方法生成视图构造器。

View::creator('profile', 'App\Http\View\Creators\ProfileCreator');

四、视图优化

官网说的很明白,恩。😂


总结一下就是:

  • 视图如果没有被编译,则会进行编译。
  • 视图如果已经被编译,则会比较是否被修改,如果被修改则重新编译。

4.1 视图预编译

# 控制台命令,预编译所有视图文件
php artisan view:cache

4.2 清除视图缓存

# 控制台命令,清除视图缓存
php artisan view:clear

五、CSRF 保护

CSRF 是一种跨站请求伪造的恶意攻击,凭借已通过身份验证的用户来运行未经过授权的命令。 如何防止 CSRF 攻击


Laravel 为每个用户的会话生成一个 CSRF 令牌,该令牌用于验证经过身份验证的用户是否是向应用程序发出请求的用户。

5.1 生成令牌

在 HTML 表单中,包含一个隐藏的 csrf 标记字段即可,提交后,在 web 中间件线里的 VerifyCsrfToken 中间件会自动验证请求的令牌与存储在会话中的令牌是否匹配。

<form method="POST" action="/profile">
    @csrf
    ...
</form>

5.2 白名单

官网的举例场景在实战中确实存在。我们一起来看一看。


有时候你可能希望设置一组不需要的 CSRF 保护的 URL 。例如,如果你正在使用 Stripe 处理付款并使用了他们的 webhook 系统,你会需要从 CSRF 的保护中排除 Stripe webhook 处理程序路由,因为 Stripe 并不会给你的路由发送 CSRF 令牌。


这时怎么办,典型做法,就是不要把这类路由放到 routes/web.php 中。


但通过 Laravel ,可以在 app/Http/Middleware/VerifyCsrfToken.php 中间件文件中,将不需要 CSRF 验证的 URL 放到 $except 属性中。

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    /**
     * 从 CSRF 验证中排除的 URI
     *
     * @var array
     */
    protected $except = [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ];
}

5.3 X-CSRF-TOKEN

除了检查 POST 参数中的 CSRF 令牌外, VerifyCsrfToken 中间件还会检查 X-CSRF-TOKEN 请求头。你应该将令牌保存在 HTML meta 标签中,如下:

<meta name="csrf-token" content="{{ csrf_token() }}">

然后,一旦创建了 mata 标签,就可以指示类似 jQuery 库自动将令牌添加到所有的请求头信息中,还可以为 ajax 提供 CSRF 保护。例如:

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

5.4 X-XSRF-TOKEN

Laravel 将当前的 CSRF 令牌存储在一个 XSRF-TOKEN cookie
中,该 cookie 包含在框架生成的每个响应中。你可以使用 cookie 值来设置 X-XSRF-TOKEN 请求头。

这个 cookie 主要是作为一种方便的方式发送的,因为一些 JavaScript 框架和库,例如 Angular 和 Axios ,会自动将它的值放入 X-XSRF-TOKEN 头中。

技巧:默认情况下,resources/js/bootstrap.js 文件包含的 Axios HTTP 库,会自动为你发送 CSRF 令牌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端木木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值