php+redis實現用戶權限判斷

php+redis實現用戶權限判斷


最近剛好有同事在寫一個基於redis的權限模塊.最開始我們這個模塊使用數據庫保存權限,但是同事說如果用戶請求大的,每一次請求都要訪問數據庫的數據庫可能會扛不住.不如把權限放到redis裏面.我redis寫的多,就幫他寫出這個代碼.

對應的代碼中有三個文件,trait.php,Auth.php兩個代碼文件,test.php一個測試文件


===

redisBase

首先我寫了一個redis連接的trait,這個是把之前寫的幾個redis類的連接方法抽取出來了,放在構造函數,再扔到一個trait裏面,這樣之後寫redis的模塊,直接放這個trait就好.如果有多個連接池或者遠程redis服務器,就修改這個trait.

/**
 * 通用的redisbase trait 鏈接數據庫
 * @author bapijun
 *
 */
trait redisBase {
    /*
     * 當前的redis
     */
    private $redis;
    function __construct($redis = [])
    {
        //$this->redis = $redis;
        $this->redis = new \Redis();
        $this->redis->connect('127.0.0.1');
    }
}

獲取權限函數

首先獲取從其他地方(我們這個項目是mysql)獲取權限.

/**
  * 獲取用戶的權限
  * @param callable $authorizeFunctiuon 回調函數,用來讀取用戶的權限
  * @param $id 用戶id
  * @return 用戶的權限
  */
 public function getAuthorize(callable $authorizeFunctiuon, $id)
 {
     return $authorizeFunctiuon($id);

 }

這裏我用了閉包函數作爲,每一次用閉包函數作爲從數據庫還是其他什麼地方獲取的函數方法.在類裏面用成員$authorizeFunctiuon,保存這個閉包函數.而這個閉包函數是獲取用戶id,當然你也可以寫成token.

爲什麼寫閉包函數,因爲我們不知道到底是從什麼環境裏面得到用戶權限.所以直接把這個獲取方法寫成參數的形式.

我在這裏類裏面還寫了另一個函數setAuthorzeFunction,保存權限函數,這樣這個閉包方法寫一次就好,之後直接就可以調用.

權限判斷

/**
 * 權限判斷函數
 * @param  [string] $checkAuthorize     需要判斷的權限
 * @param  [int] $id                 用戶id
 * @param  [callback] $authorizeFunctiuon  緩存中miss後獲取權限的方法
 * @return [bool]                    是否
 */
 public function checkAdminAuthorize($checkAuthorize, $id, $authorizeFunctiuon = null)
     {
         if ($authorizeFunctiuon != null) {
             $this->authorizeFunctiuon = $authorizeFunctiuon;
         }
         $authorizeList = $this->redis->get('member:authorize:' . $id);
         if (empty($authorizeList)) {
             //如果不存在需要去讀數據庫
             $authorizeList = $this->saveAuthorize($this->authorizeFunctiuon, $id);
         }

         $authorizeList = explode(',', $authorizeList);
         return in_array($checkAuthorize, $authorizeList) ? true : false;
     }

這是我寫的權限判斷函數,$checkAuthorize, 這裏的邏輯就比較簡單了,首先判斷是否導入新的獲取權限的方法.之後檢查當前用戶的redis中是否權限,如果沒有就去閉包方法獲取權限,並保存到緩存中.

/**
 * 獲取用戶權限並保存到緩存中
 * @param callable $authorizeFunctiuon 回調函數,用來讀取用戶的權限
 * @param $id 用戶id
 * @return redis返回值
 */
private function saveAuthorize(callable $authorizeFunctiuon, $id)
{
    $authorize = $this->getAuthorize($authorizeFunctiuon, $id);
    $this->redis->set('member:authorize:' . $id  , $authorize, Array('nx', 'ex'=>24*60*60));//設置保存事件
    return $authorize;
}

最後是判斷權限是否成立.這個方法可以自己修改,我這裏是我們項目裏面用字符串中是否存在權限判斷.

使用方法

$redis = new RedisAuth();
$id = 1;
$config = ['database_type' => 'mysql',
    'database_name' => '*****',
    'server' => 'localhost',

    'port' => 3306,
    'username' => 'user',
    'password' => '*********',

    'charset' => 'utf8',
    'option' => array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    )];
$redis->setAuthorzeFunction(function ($id) use ($config) {
    $db = new Medoo($config);
    return $db->get('tb_admin_department', 'authorizelist', ['tbid' => $id]);
});

echo $redis->checkAdminAuthorize('order.browse', 1);

其實沒什麼好說的,主要是看看閉包方法這麼寫,這裏使用use獲取外部的配置.然後在mysql中獲取.我這裏用了一個輕量級的數據庫訪問類medoo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章