/** * 派发User 令牌 * @param $wxResult * @return string * @throws Exception */ private function _grantToken($wxResult) { //拿到open_id $openId = $wxResult['openid']; //判断open_id是否存在 $id = User::getUidByOpenId($openId); //如果数据库中不存在 if (!$id) { //添加一条记录,返回新创建的id $id = User::createUser($openId); if (!$id) { throw new Exception('新增一条User失败'); } } //拼接数据为一个数组。(这个方法就是将wxResult中的openid和session_key取出,然后和用户id一起放进一个数组) $tokenValue = $this->_splicingValue($wxResult, $id); //制作令牌 //存入缓存 $token = $this->_saveCache($tokenValue); //返回token return $token; }
下面我们来看看_saveCache方法
我们将拼接成一个数组的数据$tokenValue直接传入方法中,调用一个随机字符串方法,将这个随机字符串当做key,把传入我用户数据序列化之后当作value,然后根据配置里的缓存过期时间,来存入缓存。
/** * 将令牌存入缓存,返回token * @param $tokenValue * @return string * @throws TokenException */ private function _saveCache($tokenValue) { //调用父类中的随机字符串方法 $key = parent::_makeToken(); //序列化包含id,openid,sessionKey的数组 $value = serialize($tokenValue); //在配置中取出保存时间的配置 $expriesTime = config('setting.expires_in'); //存入缓存 $result = cache($key, $value, $expriesTime); //如果存入失败,抛出异常 if (!$result) { throw new TokenException( ['errorCode' => 10003, 'message' => 'Token save fail'] ); } //返回随机字符串(也就是要返回给客户端的token) return $key; }
随机字符方法,为了提高token的安全性,让别人不那么容易的复制我们的token。我就写了这样的一个方法,大家如果有安全性更好的方法也可以使用自己想的。我就不介绍了 看代码吧
/** * 构建token随机字符串 */ public function _makeToken() { //随机抽取32位字符串方法,保存在common.php中 $randChar = randomkeys(32); //时间戳 $timestamp = time(); //配置中的盐值 $salt = config('secret.token_salt'); //拼接之后sha1加密 return sha1($randChar . $timestamp . $salt); }
这里我们就将随机生成的随机字符串返回到service层,service层再返回给控制器,控制器就可以返回给客户端了
看下完整的控制器吧
public function getToken($code = '') { //创建独立验证器,调用验证器中的验证方法 TokenCheck::instance()->goCheck(); $utObj = new UserToken($code); $token = $utObj->getUserToken(); return ['token'=>$token]; }
这样一个小程序登录换取token的流程就走完了。这个业务呢是借助微信服务器中的openid来作为唯一标识来派发token,如果不是微信的项目的话,我们同样的可以是微博登录,qq登录等第三方登录。或者自己的数据库中的id来作为唯一标识。同样可以派发token。
这里只是介绍了token的派发,还有一些token的应用,有时间的时候再写吧。今天就介绍到这里。如果有什么没有写对的地方,希望大神指正,我们共同学习。