php如何設定 token

2020-09-25 15:00:38

php設定token的方法:首先定義獲取Token的路由路徑;然後建立Service層;接著在Model層裡建立User類,並在驗證器類和異常類建立相應的驗證方法和例外處理;最後完成Token令牌的編寫即可。

推薦:《》

我們開發的後端API介面會對存取者有一個許可權要求,比如一些包含私人資訊的介面,就需要存取者請求介面的同時,傳遞一個提前已經發放給存取者的Token。

這就像一個令牌一樣,只有存取者展示出來我們才會「通過放行」。

下面就記錄一下許可權令牌的程式碼編寫思路。

一、流程概要

定義獲取Token的路由路徑,接受code引數(code來源:微信伺服器,登入系統基於微信體系)

建立Service層,在這層裡建立Token基礎類別和UserToken類

UserToken類處理整個邏輯:Token生成和返回

在Model層裡建立User類,負責使用者資料表的讀寫,供Service層的UserToken呼叫

在驗證器類和異常類建立相應的驗證方法和例外處理

控制器->Service層->Model層返回值給Service層->Service層返回值給控制器,整個流程完成Token令牌的編寫

二、具體說明

首先定義好路由路徑:

Route::post(    'api/:version/token/user',    'api/:version.Token/getToken');

然後建立Token控制器,定義對應路由路徑的getToken方法:

public function getToken($code='') {
        (new TokenGet())->goCheck($code); // 驗證器        $token = (new UserToken($code))->get();        return [            'token' => $token
        ];
    }

在呼叫Service層之前,還得檢查一下傳遞過來的引數,於是定義TokenGet這個驗證器:

class TokenGet extends BaseValidate
{
    protected $rule = [      'code' => 'require|isNotEmpty'
    ];
 
    protected $message = [        'code' => '需要code才能獲得Token!'
    ];
 }

回到Token控制器,驗證通過後,我們呼叫Service層定義的UserToken類:

$token = (new UserToken($code))->get();

這裡討論一下Service層和Model層。我們普遍的理解是Service層是基於Model層的一次抽象封裝。

Model層只負責運算元據庫並返且返回給Service層

然後Service層處理業務邏輯,最後返回給Controller層

但我覺得小專案的話,Service其實和Model就有點平級的意思,因為有些簡單的介面Model層直接對接Controller就可以了,只有相對複雜的介面,比如使用者許可權,就可以再經過Service層分隔不同功能的程式碼。

這樣的處理更加靈活,有大量確實很簡單的介面就不用過一次Service層了,這樣更像是走過過場而已,沒什麼意義了。

回到Service層的程式碼編寫,由於Token還會有不同的種類,所以先建立一個Token基礎類別,裡面包含一些通用的方法。然後就是給存取者返回令牌的UserToken類的編寫了。

由於是基於微信,我們需要三個資訊:code,appid,appsecret,然後通過建構函式來給UserToken類賦上初始值:

function __construct($code) {    $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
    );
    }

然後把這三個放入微信提供的介面的引數位置,目的是獲得一個完整的微信伺服器端的url,請求到我們需要的openid。

然後是通過傳送網路請求的步驟就在此略過。微信伺服器會返回包含openid的物件,判斷這個物件的值沒問題後,我們就開始生成令牌的步驟了,建立函數grantToken():

private function grantToken($openidObj) {
 
        // 取出openid        $openid = $openidObj['openid'];
         
        // 通過Model層呼叫資料庫,檢查openid是否已經存在        $user = UserModel::getByOpenID($openid);
         
        // 如果存在,不處理,反之則新增一條user記錄        if ($user) {            $uid = $user->id;
        } else {
            // 不存在,生成一條資料,具體方法略過            $uid = $this->newUser($openid); 
        }
         
        // 生成令牌,寫入快取(具體方法見下面的定義)        $cachedValue = $this->prepareCacheValue($openidObj, $uid);        $token = $this->saveToCache($cachedValue);
         
        // 令牌返回到呼叫者端        return $token;
}
 
private function prepareCacheValue($openidObj, $uid) {    $cachedValue = $openidObj;    $cachedValue['uid'] = $uid;    $cachedValue['scope'] = 16; // 許可權值,自己定義    return $cachedValue;
}
     
private function saveToCache($cachedValue) {    $key = self::generateToken(); // 生成令牌的方法    $value = json_encode($cachedValue);    $tokenExpire = config('setting.token_expire'); // 設定的過期時間    $request = cache($key, $value, $tokenExpire);        if (!$request) {
            throw new TokenException([            'msg' => '伺服器快取異常',            'errorCode' => 10005
        ]);
    }    return $key; // 返回令牌:token
}

可以看到,核心流程就是:

拿到openid

檢視資料庫,檢查openid是否已經存在

如果存在,不處理,反之則新增一條user記錄

生成令牌,準備快取資料,寫入快取

把令牌返回到使用者端去

其中generateToken()這個方法詳細定義如下:

public static function generateToken() {    $randomChars = getRandomChars(32); // 32個字元組成一組隨機字串    $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];  
    $salt = config('security.token_salt'); // salt 鹽
    // 拼接三組字串,進行MD5加密,然後返回    return md5($randomChars.$timestamp.$salt);
}    
function getRandomChars($length) {    $str = null;    $strPoll = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';    $max = strlen($strPoll) - 1;    for ($i = 0; $i < $length; $i++) {        $str .= $strPoll[rand(0, $max)];
    }    return $str;
}

它的主要作用毫無疑問就是生成我們的需要的令牌——Token字串。值得一提的是由於generateToken()在其他型別的Token裡也會用到,所以是放在Token基礎類別裡的。

至此,只需要把生成的令牌再返回到Controller就行了。

三、總結

令牌的編寫涉及到很多的流程,為了避免混亂,一定要注意把負責不同工作的程式碼分別定義在不同的方法裡。就像上面例子裡grantToken()方法體現的那樣,這是個核心方法,包含所有流程,但是不同的具體流程又定義在其他方法裡,然後提供給grantToken()方法呼叫。

這樣做之後grantToken()方法即使包含所有流程,但也依然很容易閱讀。

以上就是php如何設定 token的詳細內容,更多請關注TW511.COM其它相關文章!