token后台验证报错,原因如下:
模板这么写的:
{:token()}
<ul class="list2-ul clearfix">
{volist name="friendList" id="item"}
<li class="list2-ul-li">
<a class="list2-ul-li-a" href="">
<div class="img">
<img src="{$item.toUser.avatar|cdnurl=true}">
</div>
<p class="text">
{if $item.toUser.truename}
{$item.toUser.truename}
{else/}
{$item.toUser.username}
{/if}
</p>
</a>
</li>
{/volist}
</ul>
其中toUser是关联对象
后台这么写的:
$friendList=model('app\common\model\user\UserFriend')->where(["user_id"=>$this->user->id,"user_friend.status"=>20])->limit(0,8)->select();
分析:没有用到with('toUser')关联当前model对象。TP5渲染模板会再进行一次后台请求。这会导致token被刷新保存到session["__token__"]中,前端模板未二次渲染,token还是旧的token,新旧token不一致就会报token验证错误。
要点:后台未显示关联对象,前台用到相应关联对象会再请求后台一次,然而模板未刷新
后台未显示关联对象,前台用到相应关联对象会再进行一次后台请求根据(附TP5token源码:Request.php)
1.对程序打断点,会发现程序被执行了两次。
/**
* 生成请求令牌
* @access public
* @param string $name 令牌名称
* @param mixed $type 令牌生成方法
* @return string
*/
public function token($name = '__token__', $type = 'md5')
{
$type = is_callable($type) ? $type : 'md5';
$token = call_user_func($type, $_SERVER['REQUEST_TIME_FLOAT']);
if ($this->isAjax()) {
header($name . ': ' . $token);
}
Session::set($name, $token);
return $token;
}
2.渲染后的模板的cookie中的sessionId情况:
第一次渲染:
cookie:
array (size=4)
'PHPSESSID' => string 'ss8k5hoiebl7fnllpeaer70nee' (length=26)
'XDEBUG_SESSION' => string 'XDEBUG_ECLIPSE' (length=14)
'uid' => string '964821' (length=6)
'token' => string '8f7d8967-4aea-40e4-89f6-e6e161eff48e' (length=36)
token:
<input type="hidden" name="__token__" value="e50289ccac48bacdcf4b4ed0cc89b826">
第二次渲染:
cookie:
array (size=4)
'PHPSESSID' => string 'ss8k5hoiebl7fnllpeaer70nee' (length=26)
'XDEBUG_SESSION' => string 'XDEBUG_ECLIPSE' (length=14)
'uid' => string '964821' (length=6)
'token' => string '8f7d8967-4aea-40e4-89f6-e6e161eff48e' (length=36)
token:
<input type="hidden" name="__token__" value="e50289ccac48bacdcf4b4ed0cc89b826">
可以看到cookie中的sessionid没变 模板渲染的token值也没变
但是查看TP5的session文件 路径用print_r(session_save_path())查看
找到:sess_ss8k5hoiebl7fnllpeaer70nee文件
可以看到 token值不是e50289ccac48bacdcf4b4ed0cc89b826,所以会导致验证不通过
解决方法:
with方法加上关联对象
$friendList=model('app\common\model\user\UserFriend')->where(["user_id"=>$this->user->id,"user_friend.status"=>20])->limit(0,8)->with(["toUser"])->select();