使用TP框架的表单令牌功能
原理:生成一个token字符串,session中保存一次,页面中放一个;
页面发送请求时携带token字符串,控制器中进行验证,验证成功后重置。
生成token两种语法:
1.{:token()} 生成一个隐藏域, 存放token令牌
<input type="hidden" name="__token__" value="{:token()}" />
也可以使用
{:token_field()}
得到 形似以下的代码
<input type="hidden" name="__token__" value="fe9f76dcda3ee3972b23ad0428934bb7">
2.在控制器生成
<?php
namespace app\controller;
use think\Request;
use think\facade\View;
class Index
{
public function index(Request $request)
{
$token = $request->buildToken('__token__', 'sha1');
View::assign('token', $token);
return View::fetch();
}
}
然后在模板表单中使用:
<input type="hidden" name="__token__" value="{$token}" />
控制器中对token进行校验:
使用表单验证,在任何一个字段的验证规则中,加上 “token”规则
/**
* 登录
* @param Request $request
* @return \think\response\Json|void
*/
public function doLogin(Request $request){
$result = [
'code' => 200,
'msg' => 'ok',
'data' =>[]
];
// code msg data
try {
// 验证请求令牌
$check = $request->checkToken('__token__');
if(false === $check) {
throw new ValidateException('invalid token');
}
$username = $request->post('username');
$password = $request->post('password');
# 验证非空
validate(\app\admin\validate\Login::class)->check([
'username' => $username,
'password' => $password,
]);
$adminInfo = Manager::where('username','=',"{$username}")->find();
if ($adminInfo) {
// 判断密码
if ($adminInfo->password == encryptPassword($password)) {
Session::set('username',$adminInfo->username);//session
#记录日志信息
Log::write($username.'登录成功','info');
return redirect('/admin/goodsList');
} else{
throw new \think\Exception('密码错误', 20002);
}
} else {
abort(20001,'用户名不存在');
}
}catch (ValidateException $exception) {
$result['msg'] = $exception->getError();
return json($result);
}catch (\Exception $exception) {
Log::write('测试日志信息,这是警告级别,并且实时写入','notice');
$result['msg'] = $exception->getMessage();
$result['code'] = $exception->getCode();
return json($result);
}
}
AJAX提交
如果是AJAX提交的表单,可以将token设置在meta中
<meta name="csrf-token" content="{:token()}">
或者直接使用
{:token_meta()}
也可以在全局Ajax中使用这种方式设置X-CSRF-Token
请求头并提交:
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}