(一开始就被web的session机制搞懵了,结果发现和微信小程序token机制不一样,先感谢下琳姐姐把我从杂乱无章的代码里拯救出来…)
首先小程序登陆的时候会post用户名,密码和微信小程序用户登录时获取的code码到服务端。
然后去获得token,id是user表中与各个账号唯一对应的id,也是通过token验证后要去获得用户的唯一标识,id通过用户名和密码去表中select id获得
//获得token
$tk = $TokenModel->get_token($data['code'],$id);
详细看一下get_token函数
/*
* @ 注册或者登录获取token令牌
* @ $code 小程序获取的code码
*/
public function get_token($code,$id) {
$ut = new UserToken($code);
$token = $ut->gett($code,$id);
return $token;
}
接着看gett函数 首先是一大堆wx的参数去获得sprintf一个网址,判断wxResult的结果,没问题就去取token
public function gett($code,$id){
$this->code = $code;
$this->wxAppID = config('wx.app_id');
$this->wxAppSecret = config('wx.app_secret');
$this->wxLoginurl = sprintf(config('wx.login_url'),
$this->wxAppID,$this->wxAppSecret,$this->code);
$result = curl_get($this->wxLoginurl);
//返回的字符串变成数组,true是数组,false是对象
$wxResult = json_decode($result, true);
if (empty($wxResult)){
throw new Exception('获取session_key及openID时异常,微信内部错误');
}
else{
$loginFail = array_key_exists('errcode',$wxResult);
if ($loginFail){
$this->processLoginError($wxResult);
}else{
//检测没有报错的话就去取token
return $this->grantToken($wxResult,$id);
}
}
}
接着看grantToken函数,经过一大长串的验证id还有检测
public function grantToken($wxResult,$id){
//验证id
(new IDMustBeNumber())->goToCheck([
'id' => $id
]);
//检验id在的时候,这里的openid等于它
$openid = $wxResult['openid'];
$user = Db::table('user')->where([
'id' => $id
])->field('openid')->find();
$user_openid = $user['openid'];
//检测是否绑定
$check_exist = Db::table('user')->where(['openid' => $openid])->find();
if ($check_exist){
if ($check_exist['id'] != $id){
throw new BaseException([
'msg' => '您的微信号已经绑定过一个账号了,不可重复关联!'
]);
}
}
if ($user_openid == NULL){
$integrity = Db::table('user')->where([
'id' => $id
])->update([
'openid' => $openid
]);
if (!$integrity){
throw new BaseException([
'msg' => '您的微信号已经绑定过一个账号了,不可重复关联!'
]);
}
}else{
if ($user_openid != $openid){
throw new LoginException([
'msg' => '微信号与用户账号不匹配!'
]);
}
}
这些都不重要,主要看token的获取,这里的key就是token,用的是32随机+时间戳+salt
获得,保证唯一性而已
public function gettoken(){
//用三组字符串md5加密
//32个字符组成一组随机字符串
$randChars = getRandChars(32);
//时间戳
$timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
//salt 盐
$salt = config('setting.token_salt');
$key = md5($randChars.$timestamp.$salt);
return $key;
}
重点在这
这里直接用了TP的cache机制 ,将token设为Cache的key,用户的id设为value,然后每次前端请求接口的时候只要给我们token,我们就可以获取到用户的id并且拿到他的信息。
通过cache($key, $value, $expire_in)进行缓存
$this->uid = $id;
//这是一个拼接token的函数,32随机+时间戳+salt
//key就是token,value包含uid,scope
//拿到钥匙
$key = $this->gettoken();
$cachedValue['id'] = $id;
//scope为权限
$cachedValue['secret'] = 16;
$this->secret = 16;
$value = json_encode($cachedValue);
//设置存活时间
$expire_in = config('setting.token_expire_in');
//存入缓存
$request = cache($key, $value, $expire_in);
if (!$request){
throw new TokenException([
'msg' => '服务器缓存异常',
]);
}
return $key;
后台缓存好token,客户端请求服务端的时候带上token,后台取校验token并获取id就好啦
public function get_id(){
$token = input('post.token');
$vars = Cache::get($token);
if (!$vars){
exit(json_encode([
'code' => 401,
'msg' => 'Token已经过期或无效Token!'
],JSON_UNESCAPED_UNICODE));
}else{
if (!is_array($vars)){
$vars = json_decode($vars,true);
}
if (array_key_exists('username',$vars)) {
return $vars['username'];
}else{
exit(json_encode([
'code' => 444,
'msg' => '尝试获取的Token变量并不存在!'
],JSON_UNESCAPED_UNICODE));
}
}
}