1. 程式人生 > >小程式之Token的獲取(PHP)

小程式之Token的獲取(PHP)

token是在輸入了使用者名稱和密碼之後獲取的,利用這個token你可以擁有檢視或者操作相應的資源的許可權。

接下來直接上程式碼,裡面有詳細註釋。

controller/token
<?php
/**
 * Created by PhpStorm.
 * User: wzs
 * Date: 2018/3/14
 * Time: 10:07
 */

namespace app\api\controller\v1;


use app\api\service\UserToken;
use app\api\validate\TokenGet;

class Token
{
    public function getToken($code=''){
        (new TokenGet())->goCheck();
        $ut = new UserToken();
        $token = $ut->get($code);
        return [
            'token' => $token
        ];
    }
}
service/Token
<?php
/**
 * Created by PhpStorm.
 * User: wzs
 * Date: 2018/3/15
 * Time: 16:29
 */

namespace app\api\service;


use app\lib\exception\TokenException;
use think\Cache;
use think\Exception;
use think\Request;

class Token
{
    //生成令牌
    public static function generateToken(){
        //32 個字元組成一組隨機字串
        $randChars = getRanChar(32);
        //用三組字串進行md5加密
        $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
        // salt 鹽
        $salt = config('secure.token_salt');
        return md5($randChars.$timestamp.$salt);
    }

    public static function getCurrentTokenVar($key){
        $token = Request::instance()->header('token');
        $vars = Cache::get($token);
        if(!$vars){
            throw new TokenException();
        }
        else{
            if(!is_array($vars)){
                $vars = json_decode($vars,true); // 字串變陣列
            }
            if(array_key_exists($key,$vars)){
                return $vars[$key];
            }
            else{
                throw new Exception('嘗試獲取的token變數並不存在');
            }
        }
    }
    //
    public static function getCurrentUid(){
        // token
        $uid = self::getCurrentTokenVar('uid');
        return $uid;
    }
}
service/UserToken
<?php
/**
 * Created by PhpStorm.
 * User: wzs
 * Date: 2018/3/14
 * Time: 10:32
 */

namespace app\api\service;


use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User as UserModel;

class UserToken extends Token
{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    function __construct($code)
    {
        $this->code = $code;
        $this->wxAppID = config('wx.app_id');
        $this->wxAppSecret = config('wx.app_secret');
        //sprintf函式   把url中的s% 替換成想要的資料
        $this->wxLoginUrl = sprintf(config('wx.login_url'),$this->wxAppID,$this->wxAppSecret,$this->code);
    }

    public function get()
    {
        $result = curl_get($this->wxLoginUrl);
        $wxResult = json_decode($result, true);//result 變成json字串
        if (empty($wxResult)) {
            throw new Exception('獲取session_key及openID時異常,微信內部錯誤');
        } else {
            $loginFail = array_key_exists('errcode', $wxResult);
            if ($loginFail) {
                $this->processLoginError($wxResult);
            }
            else {
                return $this->grantToken($wxResult);
            }
        }
    }

    //封裝一個成功接收code的方法
    private function grantToken($wxResult){
        //拿到openID
        //資料庫裡看一下,openID是否存在
        //如果存在則不處理,不存在新增一條記錄
        //生成令牌,準備快取資料,寫入快取
        //把令牌返回到客戶端
        // key 令牌
        // value  :wxResult,uid,scope
        $openid = $wxResult['openid'];
        $user = UserModel::getByOpenID($openid);
        if($user){
            $uid = $user->id;
        }
        else{
            $uid = $this->newUser($openid);
        }
        $cachedValue = $this->preparCacheValue($wxResult,$uid);
        $token = $this->saveToCache($cachedValue);
        return $token;
    }


    // 寫入快取
    private function saveToCache($cachedValue){
        $key = self::generateToken();
        $value = json_encode($cachedValue);//把陣列轉換成字串
        $expire_in = config('setting.token_expire_in');

        $request = cache($key,$value,$expire_in);
        if(!$request){
            throw new TokenException([
                'msg' => '伺服器快取異常',
                'errorCode' => 10005
            ]);
        }
        return $key;
    }
    //準備value的一系列資料
    private function preparCacheValue($wxResult,$uid){
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
        $cachedValue['scope'] = 16;  //許可權高低2,4,6,8,12,14,16
        return $cachedValue;
    }
    //openID不存在  則新增一條記錄
    private function newUser($openid){
        $user = UserModel::create([
            'openid' => $openid
        ]);
        return $user->id;
    }
    //封裝一個丟擲異常的方法
    private function processLoginError($wxResult){
        throw new WeChatException([
            'msg' => $wxResult['errmsg'],
            'errcode' => $wxResult['errcode']
        ]);
    }

}
validate/BaseValidate
<?php
/**
 * Created by PhpStorm.
 * User: wzs
 * Date: 2018/3/6
 * Time: 16:46
 */

namespace app\api\validate;

use app\lib\exception\ParameterException;
use think\Exception;
use think\Request;
use think\Validate;

class BaseValidate extends Validate
{
    public function goCheck(){
        // 獲取http傳入的引數
        // 對這些引數做校驗
        $request = Request::instance();
        $params = $request->param();

        $result = $this->batch()->check($params);
        if(!$result){
            $ex = new ParameterException([
                'msg' => $this->error,
            ]);
            throw $ex;
        }
        else{
            return true;
        }
    }

    protected function isPositiveInteger($value,$rule = '',$data = '',$field = ''){
        if(is_numeric($value) && is_int($value+0) && ($value+0) > 0){
            return true;
        }
        else{
            return false;
//            return $field."必須是正整數";
        }
    }

    protected function isNotEmpty($value,$rule = '',$data = '',$field = ''){
        if(empty($value)){
            return false;
        }
        else{
            return true;
        }
    }
}

validate/TokenGet
<?php
/**
 * Created by PhpStorm.
 * User: wzs
 * Date: 2018/3/14
 * Time: 10:09
 */

namespace app\api\validate;


class TokenGet extends BaseValidate
{
    protected $rule = [
        'code' => 'require|isNotEmpty'
    ];
    protected $message = [
        'code' => '沒有code還想獲取Token,做夢呢'
    ];
}