使用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.在控制器生成
<?phpnamespace 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 datatry {// 验证请求令牌$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')}