TP5框架 微信小程序接口开发之Token令牌鉴权流程

获取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是否存在

//验证用户传过来的token 是否有效
    public static function verifyToken($token)
    {
        $exist = Cache::get($token);
        if($exist){
            return true;
        }
        else{
            return false;
        }
    }
发布了16 篇原创文章 · 获赞 6 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/LGDmar/article/details/95457012