获取token,客户端第一次请求服务端通过用户id
1.编写token封装js
import { Config } from 'config.js';
//获取应用实例
const app = getApp();
class Token {
constructor() {
//检验令牌地址
this.verifyUrl = Config.resultUrl + 'token/verify';
//获取token地址
this.TokenUrl = Config.resultUrl + 'token/user';
}
//校验缓存令牌是否存在
verify() {
var token = wx.getStorageSync('token');
var that = this;
//判断令牌是否存在
if (!token) {
//不存在则重新获取令牌
that.getTokenFromServer();
}else {
//存在则调用服务器检测令牌是否失效的接口
that._veirfyFromServer(token);
}
}
//检测token是否失效
_veirfyFromServer(token){
var that = this;
wx.request({
url: that.verifyUrl,
method: 'POST',
data: {
token: token
},
success: function (res) {
//为true 表示令牌没有失效
var valid = res.data;
if(!valid){
//令牌失效则重新获取令牌
that.getTokenFromServer();
}
}
})
}
//获取token
getTokenFromServer() {
var that = this;
wx.login({
success: function (res) {
data['code'] = res.code;
wx.request({
url: that.TokenUrl,
method: 'POST',
success: function (res) {
//将token存入缓存
wx.setStorageSync('token', res.data.token);
}
})
}
})
}
}
export {Token};
2.创建访问接口基类base.js
import { Config } from "config.js";
import { Token } from 'token.js';
class Base {
constructor() {
//config封装的接口URL
this.BaseRequestUrl = Config.resultUrl;
}
//http 请求类, 当noRefech为true时,不做未授权重试机制
request(params, noRefetch) {
var that = this;
var url = this.BaseRequestUrl + params.url;
//如果未设置请求参数,则默认GET
if (!params.method) {
params.type = 'GET';
}
//请求接口
wx.request({
url: url,
data: params.data,
method: params.method,
header: {
'content-type': 'application/json',
'token': wx.getStorageSync('token') //获取缓存的token
},//token
success: function (res) {
// 判断以2(2xx)开头的状态码为正确
// 异常不要返回到回调中,就在request中处理,记录日志并showToast一个统一的错误即可
var code = res.statusCode.toString();
var startChar = code.charAt(0);
if (startChar == '2') {
//token验证成功
params.sCallback && params.sCallback(res.data);
} else {
//token验证失败重新调用获取token
if (code == '401') {
//如果再出现401就不在继续调用了
//noRefetch取非就是false条件不成立不继续调用了
if (!noRefetch) {
that._refetch(params);
}
}
//如果不在进行重发机制就返回
if (noRefetch) {
//发生错误执行的回调函数eCallback
params.eCallback && params.eCallback(res.data);
}
}
}, fail: function (err) {
}
})
}
_refetch(params) {
//实例化token
var token = new Token();
//重新调用获取token方法
token.getTokenFromServer((res) => {
//二次调用request方法
this.request(params, true);
});
}
}
export { Base };
3.TP5创建路由
4.获取token并返回
//获取token
public function get(){
//回调当前微信用户http参数
$result = https_request($this->wxLoginUrl);
//json字符串转数组
$wx_result = json_decode($result,true);
//判断结果是否为空
if(empty($wx_result)){
throw new Exception('获取session_key及openID异常,微信内部错误');
}else{
$loginFail = array_key_exists('errcode',$wx_result);
if ($loginFail){
//存在表示错误
$this->processLoginError($wx_result);
}else{
$result = $this->granToken($wx_result);
//成功拿到令牌和用户信息,返回给服务端
return $result;
}
}
}
//抛出错误
private function processLoginError($wx_result){
throw new WeChatException([
'msg'=> $wx_result['errmsg'],
'errorCode'=> $wx_result['errcode']
]);
}
//生成令牌
private function granToken($wx_result){
//key:令牌
//value:wxResult,uid,scope
//拿到openid
$openid = $wx_result['openid'];
//查看数据库是否存在当前用户
$user = OpenidModel::getByOpenID($openid);
//如果存在则不处理,不存在新增user记录,获取用户mid号
if($user){
$uid = $user->mid;
}else{
$uid = 0;
}
//生成令牌,准备缓存数据,写入缓存
$cachaedValue = $this->prepareCachedValue($wx_result,$uid);
//把令牌返回客户端
$token = $this->saveToCacha($cachaedValue);
$arr = [];
$arr['userid'] = $uid;
$arr['token'] = $token;
$arr['openid'] = $openid;
return $arr;
}
//用户信息拼接成数组
private function prepareCachedValue($wx_result,$uid){
$cachaedValue = $wx_result;
$cachaedValue['uid']=$uid;
//scope=16 代表APP用户的权限数值
//scope=32 代表(管理员)用户的权限数值
$cachaedValue['scope']= 16;
return $cachaedValue;
}
//写入缓存
private function saveToCacha($cachaedValue){
//获取token
$key = self::generateToken();
//用户信息,openid权限等
$value = json_encode($cachaedValue);
//token有效期
$expire_in = config('setting.token_expire_in');
//tp5自带缓存写入,用token作为key
$request = cache($key,$value,$expire_in);
if(!$request){
throw new TonkenException([
'msg'=>"服务器缓存异常",
'errorCode'=> 10005
]);
}
//返回token
return $key;
}
//生成令牌字符串
public static function generateToken(){
//32个字符组成一组随机的字符串
$randChars = getRandChar(32);
//用三组,字符串进行md5加密
$timestamp = time();
//slat 盐
$salt = config('secure.token_salt');
return md5($randChars.$timestamp.$salt);
}
//获取随机字符串
function getRandChar($length){
$str = null;
$strPol = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
$max = strlen($strPol) - 1;
for ($i=0;$i<$length;$i++){
$str.=$strPol[rand(0,$max)];
}
return $str;
}
5.生成token 盐 配置文件
6.校验token是否正确和获取token接口控制器
7.继续校验token,查看服务端缓存token是否存在
扫描二维码关注公众号,回复:
10783086 查看本文章
//验证用户传过来的token 是否有效
public static function verifyToken($token)
{
$exist = Cache::get($token);
if($exist){
return true;
}
else{
return false;
}
}