直接上例子
表单如下
<div class="login-container">
<div class="loginbox bg-white">
<div class="loginbox-title">登录</div>
<div class="loginbox-or">
<div class="or-line"></div>
</div>
<form method="post">
<input type="hidden" name="__token__" value="{$Request.token}" />
<div class="loginbox-textbox">
<input type="text" name="username" class="form-control" placeholder="用户名" />
</div>
<div class="loginbox-textbox">
<input type="text" name="password" class="form-control" placeholder="密码" />
</div>
<div class="loginbox-textbox">
<input name="captcha" type="text" class="form-control" placeholder="验证码" aria-describedby="basic-addon2">
<span class="input-group-addon" id="basic-addon2"><img src="{:captcha_src()}" id="img" alt="captcha" /></span>
</div>
<div class="loginbox-forgot">
<a href="">忘记密码?</a>
</div>
<div class="loginbox-submit">
<input type="button" id="login" class="btn btn-primary btn-block" value="Login">
</div>
</form>
<div class="loginbox-signup">
<a href="{:url('admin/index/register')}">注册账户</a>
</div>
</div>//使用ajax提交
$.ajax({ url:"{:url('admin/index/login')}", type:'post', data:$('form').serialize(), retType:'json', success:function (ret) { if (ret.code==1) { layer.msg(ret.msg,{ icon:6, time:2000 },function () { location.href=ret.url; } ) }else { layer.open({ title:'登录失败', content:ret.msg, icon: 5, anim:6 }) } }})
</div>
验证规则如下
protected $rule = [
'username|用户名'=>'token|require',
'password|密码'=>'require',
'captcha|验证码'=>'require|captcha',
'repassword'=>'require|confirm:password',
'email|邮箱'=>'require|email'
];
第一次提交,将token提交验证没有问题(只要token被验证一次),第二次提交(ajax请求),由于是异步请求整个页面并没有刷新,自然无法获得新的token,则不能通过验证

解决方法
1 在控制器中使用生成新的token并返回
$ret=model('Admins')->login($data);
//动态生成token,返回到视图中
//不要写在模型的验证前面 token方法中会保存session('__token__'),会设置新的token覆盖前面的token 使得验证永远不会成功
$token=$request->token();
if ($ret===true)
$this->success('登录成功',url('admin/home/index'));
elseif($ret===false)
$this->error('登录失败:密码错误',url('admin/index/login'),["token"=>$token]);
elseif($ret===0)
我设置的ajax接受的数据类型为json格式 thinkphp会自动将ajax请求返回json格式
2 在视图中设置新的token
//刷新验证码
$('#img').attr('src',"{:captcha_src()}")
//刷新token ret success为返回的
$("input:hidden").attr('value',ret.data.token)
layer.open({
title:'登录失败',
content:ret.msg,
icon: 5,
anim:6