qiansion / think-csrf
防止CSRF攻击中间件
Requires
- topthink/framework: >=6.0
This package is auto-updated.
Last update: 2024-09-30 01:20:31 UTC
README
这是一个基于thinkphp6.x封装的防止CSRF攻击的composer包
为什么要封装think-csrf
thinkphp官方的表单令牌实际上从实际开发角度来看,它只适合用来防止表单重复提交(尽管官方文档中说可以防止CSRF攻击)。因为框架在验证表单令牌通过后会立即删除session中的token,这样对于ajax提交方式非常不友好,因为页面没有刷新而session中的表单令牌已经更新,导致再次提交表单会失败。该依赖包就是用来解决这个问题,且验证CSRF的token值是长时间保存在cookie中的,相对于官方表单令牌保存在session中不会过期,并且减轻服务端压力的特点。
防止表单重复提交和防止CSRF攻击应该分开来做,你在使用think-csrf的同时也不影响你使用tp官方的表单令牌,它们不会产生冲突
安装
composer require qiansion/think-csrf
配置
安装完毕后会在app/config目录下自动生成csrf.php配置文件。
<?php
return [
//cookie中的key(可自行更换)
'cookie_key' => '0cc175b9c0f1b6a831c399e269772661',
//传递的csrf参数名称
'param_key' => '_token',
];
使用
think-csrf默认是没有开启的(API应用通常不需要使用think-csrf),如果你需要使用think-csrf,需要在全局的中间件定义文件中加上下面的中间件定义:
\qiansion\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值 |