天天看點

微信小程式登入授權

<?php
class login{
    public function wxLogin() {
        /**
        * 3.小程式調用server擷取token接口, 傳入code, rawData, signature, encryptData.
        */
        $code = input("code", '', 'htmlspecialchars_decode');
        $rawData = input("rawData", '', 'htmlspecialchars_decode');
        $signature = input("signature", '', 'htmlspecialchars_decode');
        $encryptedData = input("encryptedData", '', 'htmlspecialchars_decode');
        $iv = input("iv", '', 'htmlspecialchars_decode');
        
        /**
        * 4.server調用微信提供的jsoncode2session接口擷取openid, session_key, 調用失敗應給予用戶端回報
        * , 微信側傳回錯誤則可判斷為惡意請求, 可以不傳回. 微信文檔連結
        * 這是一個 HTTP 接口,開發者伺服器使用登入憑證 code 擷取 session_key 和 openid。其中 session_key 是對使用者資料進行加密簽名的密鑰。
        * 為了自身應用安全,session_key 不應該在網絡上傳輸。
        * 接口位址:"https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code"
        */
        $params = [
        'appid' => $this->appid,
        'secret' => $this->secret,
        'js_code' => $code,
        'grant_type' => $this->grant_type
        ];
        $res = makeRequest($this->url, $params);
        
        if ($res['code'] !== 200 || !isset($res['result']) || !isset($res['result'])) {
        return json(ret_message('requestTokenFailed'));
        }
        $reqData = json_decode($res['result'], true);
        if (!isset($reqData['session_key'])) {
        return json(ret_message('requestTokenFailed'));
        }
        $sessionKey = $reqData['session_key'];
        
        /**
        * 5.server計算signature, 并與小程式傳入的signature比較, 校驗signature的合法性, 不比對則傳回signature不比對的錯誤. 不比對的場景可判斷為惡意請求, 可以不傳回.
        * 通過調用接口(如 wx.getUserInfo)擷取敏感資料時,接口會同時傳回 rawData、signature,其中 signature = sha1( rawData + session_key )
        *
        * 将 signature、rawData、以及使用者登入态發送給開發者伺服器,開發者在資料庫中找到該使用者對應的 session-key
        * ,使用相同的算法計算出簽名 signature2 ,比對 signature 與 signature2 即可校驗資料的可信度。
        */
        $signature2 = sha1($rawData . $sessionKey);
        
        if ($signature2 !== $signature) return ret_message("signNotMatch");
        
        /**
        *
        * 6.使用第4步傳回的 session_key 解密 encryptData , 将解得的資訊與 rawData 中資訊進行比較, 需要完全比對,
        * 解得的資訊中也包括openid, 也需要與第4步傳回的openid比對. 解密失敗或不比對應該傳回客戶相應錯誤.
        * (使用官方提供的方法即可)
        */
        $pc = new WXBizDataCrypt($this->appid, $sessionKey);
        $errCode = $pc->decryptData($encryptedData, $iv, $data );
        
        if ($errCode !== 0) {
        return json(ret_message("encryptDataNotMatch"));
        }
        
        
        /**
        * 7.生成第三方3rd_session,用于第三方伺服器和小程式之間做登入态校驗。為了保證安全性,3rd_session應該滿足:
        * a.長度足夠長。建議有2^128種組合,即長度為16B
        * b.避免使用srand(目前時間)然後rand()的方法,而是采用作業系統提供的真正随機數機制,比如Linux下面讀取/dev/urandom裝置
        * c.設定一定有效時間,對于過期的3rd_session視為不合法
        *
        * 以 $session3rd 為key,sessionKey+openId為value,寫入memcached
        */
        $data = json_decode($data, true);
        $session3rd = randomFromDev(16);
        
        $data['session3rd'] = $session3rd;
        cache($session3rd, $data['openId'] . $sessionKey);
        
         
        
        return json($data);
        }
}

?>