ajiho/think-csrf

Thinkphp6 解决CSRF攻击

V1.0.0 2022-08-16 07:17 UTC

This package is auto-updated.

Last update: 2024-09-20 09:41:53 UTC


README

这是一个基于Thinkphp6.x封装的防止CSRF攻击的Composer包。

为什么还需要封装think-csrf?

Thinkphp官方的表单令牌实际上从实际开发的角度来说,它仅适用于防止表单重复提交(尽管官方文档中说可以防止CSRF攻击)。因为框架在验证表单令牌后会立即删除session中的token,这对于ajax提交的方式非常不友好,因为页面没有刷新而session中的表单令牌已经更新,导致再次提交表单会失败。该依赖包就是用来解决这个问题,且验证CSRF的token值是长时间保存在cookie中的,相对于官方表单令牌保存在session中有不会过期、减轻服务端压力的特点。

防止表单重复提交和防止CSRF攻击应该分开来做,你在使用think-csrf的同时也不影响你使用tp官方的表单令牌,它们不会产生冲突。

安装

composer require ajiho/think-csrf

配置

/config/csrf.php

<?php
return [
    //cookie中的key(可自行更换)
    'cookie_key' => '0cc175b9c0f1b6a831c399e269772661',
    //传递的csrf参数名称
    'param_key' => '_token',
];

使用

\ajiho\middleware\VerifyCsrfToken::class

表单提交

以下示例是基于think-smarty模板引擎定义的,如果你是tp框架自带的模板引擎,那么调用函数的语法应该是{:csrf_field()}

<form action="" method="post">
    <{ csrf_field() }>
  <div class="form-group">
  <label for="email">Email address:</label>
  <input type="email" class="form-control" placeholder="Enter email" id="email">
  </div>
  <div class="form-group">
  <label for="pwd">Password:</label>
  <input type="password" class="form-control" placeholder="Enter password" id="pwd">
  </div>
  <div class="form-group form-check">
  <label class="form-check-label">
    <input class="form-check-input" type="checkbox"> Remember me
  </label>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

AJAX提交

如果是AJAX提交的表单,可以将token设置在meta

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

或在视图文件中直接调用csrf_meta()函数也能生成上面的meta标签

然后在全局Ajax中使用这种方式设置X-CSRF-Token请求头并提交:

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

助手函数

csrf_field()

返回一个携带token的隐藏域

csrf_meta()

返回一个携带token的meta标签

csrf_token()

只返回token值