微信小程序的登陸
1、小程序獲取openid, session_key
一、獲取code,有效期五分鐘,只能使用一次
二、使用code獲取openid, session_key, [unionid]
wx.login({
success: res => {
// 發送 res.code 到後臺換取 openId, sessionKey, unionId
console.log(res);
wx.request({
url: 'http://localhost/mpserver/login.php',
data: {
code: res.code
},
method: 'GET',
success: function(res) {
console.log(res.data)
}
})
}
})
<!-- 若是隻是展現用戶頭像暱稱,可使用 <open-data /> 組件 -->
<open-data type="userAvatarUrl"></open-data>
<open-data type="userNickName"></open-data>
2、獲取用戶詳細信息:受權
一、已受權過
已受權:wx.getUserInfo()
當用戶未受權過,調用該接口將直接進入fail回調
當用戶受權過,可使用該接口獲取用戶信息
如今的調用此接口沒有彈框
app.js---------------------
onLoad: function() {
// 查看是否受權
wx.getSetting({
success: function(res){
if (res.authSetting['scope.userInfo']) {
// 已經受權,能夠直接調用 getUserInfo 獲取頭像暱稱,不會彈框,不是實時更新的,大概是兩小時
wx.getUserInfo({
withCredentials: false,
success: function(res) {
// 能夠將 res 發送給後臺解碼出 unionId
this.globalData.userInfo = res.userInfo;
this.globalData.userInfo.openid = this.globalData.user.openid;
this.globalData.userInfo.session_key = this.globalData.user.session_key;
// 因爲 getUserInfo 是網絡請求,可能會在 Page.onLoad 以後才返回
// 因此此處加入 callback 以防止這種狀況
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
注:當 withCredentials 爲 true 時,要求此前有調用過 wx.login 且登陸態還沒有過時,此時返回的數據會包含 encryptedData, iv 等敏感信息;當 withCredentials 爲 false 時,不要求有登陸態,返回的數據不包含 encryptedData, iv 等敏感信息。
二、未受權:要求以按鈕的形式告知用戶去點擊來受權
<button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 獲取頭像暱稱 </button>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
login.js---------------------
Page({
data: {
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo')
},
//事件處理函數
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
} else if (this.data.canIUse){
// 因爲 getUserInfo 是網絡請求,可能會在 Page.onLoad 以後才返回
// 因此此處加入 callback 以防止這種狀況
app.userInfoReadyCallback = res => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
} else {
// 在沒有 open-type=getUserInfo 版本的兼容處理
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}
},
// 受權並返回用戶信息
getUserInfo: function(e) {
console.log(e)
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
})
返回:
userInfo OBJECT 用戶信息對象,不包含 openid 等敏感信息
rawData String 不包括敏感信息的原始數據字符串,用於計算簽名。
signature String 使用 sha1( rawData + sessionkey ) 獲得字符串,用於校驗用戶信息,參考文檔 signature。
encryptedData String 包括敏感數據在內的完整用戶信息的加密數據,詳細見加密數據解密算法
iv String 加密算法的初始向量,詳細見加密數據解密算法
userInfo包含信息:
avatarUrl
city
country
gender
language
nickName
province
若是須要openid,unionid等信息,須要請求服務端解密encryptedData
getUserInfo: function(e) {
console.log(e);
var self = this;
wx.request({
url: 'http://localhost/mpserver/decrypt.php',
data: {
session_key: app.globalData.user.session_key,
encrypted_data: e.detail.encryptedData,
iv: e.detail.iv
},
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success: function(res) {
console.log(res.data)
app.globalData.userInfo = res.data
self.setData({
userInfo: res.data,
hasUserInfo: true
})
}
})
}
服務端:
decrypt.php--------------------------------------------------------
<?php
date_default_timezone_set('Asia/Shanghai');
header('Content-Type:application/json; charset=utf-8');
require_once('lib/wxBizDataCrypt.php');
$appid = 'wx89137bb28d7cd3e6';
$sessionKey = $_POST['session_key'];
$encryptedData = $_POST['encrypted_data'];
$iv = $_POST['iv'];
$pc = new WXBizDataCrypt($appid, $sessionKey);
$errCode = $pc->decryptData($encryptedData, $iv, $data );
if ($errCode == 0) {
exit($data);
} else {
exit(json_encode(['status'=>false, 'errcode'=>$errCode]));
}
wxBizDataCrypt.php------------------------------------------------
<?php
/**
* 對微信小程序用戶加密數據的解密示例代碼.
*
* @copyright Copyright (c) 1998-2014 Tencent Inc.
*/
include_once "errorCode.php";
class WXBizDataCrypt
{
private $appid;
private $sessionKey;
/**
* 構造函數
* @param $sessionKey string 用戶在小程序登陸後獲取的會話密鑰
* @param $appid string 小程序的appid
*/
public function __construct( $appid, $sessionKey)
{
$this->sessionKey = $sessionKey;
$this->appid = $appid;
}
/**
* 檢驗數據的真實性,而且獲取解密後的明文.
* @param $encryptedData string 加密的用戶數據
* @param $iv string 與用戶數據一同返回的初始向量
* @param $data string 解密後的原文
*
* @return int 成功0,失敗返回對應的錯誤碼
*/
public function decryptData( $encryptedData, $iv, &$data )
{
if (strlen($this->sessionKey) != 24) {
return ErrorCode::$IllegalAesKey;
}
$aesKey=base64_decode($this->sessionKey);
if (strlen($iv) != 24) {
return ErrorCode::$IllegalIv;
}
$aesIV=base64_decode($iv);
$aesCipher=base64_decode($encryptedData);
$result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
$dataObj=json_decode( $result );
if( $dataObj == NULL )
{
return ErrorCode::$IllegalBuffer;
}
if( $dataObj->watermark->appid != $this->appid )
{
return ErrorCode::$IllegalBuffer;
}
$data = $result;
return ErrorCode::$OK;
}
}
errorCode.php-------------------------------------------------------
class ErrorCode
{
public static $OK = 0;
public static $IllegalAesKey = -41001;
public static $IllegalIv = -41002;
public static $IllegalBuffer = -41003;
public static $DecodeBase64Error = -41004;
}
解密後的信息:
{
"openId": "OPENID",
"nickName": "NICKNAME",
"gender": GENDER,
"city": "CITY",
"province": "PROVINCE",
"country": "COUNTRY",
"avatarUrl": "AVATARURL",
"unionId": "UNIONID",
"watermark":
{
"appid":"APPID",
"timestamp":TIMESTAMP
}
}
總結:
一、應用初始化 wx.login() ---> code ---> 服務端獲得openid,session_key,unionid綁定到本系統的用戶信息user ---> 將user返回給小程序(過濾掉openid,session_key,unionid參數) ---> 將userid做爲小程序和服務端通信的標識。
二、若是已經受權過:wx.getUserInfo(),withCredentials: false,獲取基本信息。
關於安全:
附加:
一、wx.request()方法說明,對於get,post方式有所不一樣,默認請求方式get
data 數聽說明:
最終發送給服務器的數據是 String 類型,若是傳入的 data 不是 String 類型,會被轉換成 String 。轉換規則以下:
對於 GET 方法的數據,會將數據轉換成 query string(encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...)
對於 POST 方法且 header['content-type'] 爲 application/json 的數據,會對數據進行 JSON 序列化,默認如此。
對於 POST 方法且 header['content-type'] 爲 application/x-www-form-urlencoded 的數據,會將數據轉換成 query string (encodeURIComponent(k)=encodeURIComponent(v)&encodeURIComponent(k)=encodeURIComponent(v)...)
所以對於POST請求咱們應該設置
header: {
'content-type': 'application/x-www-form-urlencoded'
},
二、在wx.request()裏面使用this表示該函數內部,若是想要設置值得話,須要換一個變量,在wx.request()外面 var self = this; 在wx.request()裏面能夠
self.globalData.user = res.data;來賦值,由於this是不存在globalData這個變量的,只有外部有這個變量。
三、關於session_key
開發者若是遇到由於session_key不正確而校驗簽名失敗或解密失敗,請關注下面幾個與session_key有關的注意事項。
wx.login()調用時,用戶的session_key會被更新而導致舊session_key失效。開發者應該在明確須要從新登陸時才調用wx.login(),及時經過登陸憑證校驗接口更新服務器存儲的session_key。
微信不會把session_key的有效期告知開發者。咱們會根據用戶使用小程序的行爲對session_key進行續期。用戶越頻繁使用小程序,session_key有效期越長。
開發者在session_key失效時,能夠經過從新執行登陸流程獲取有效的session_key。使用接口wx.checkSession()能夠校驗session_key是否有效,從而避免小程序反覆執行登陸流程。
當開發者在實現自定義登陸態時,能夠考慮以session_key有效期做爲自身登陸態有效期,也能夠實現自定義的時效性策略。
---------------------
原文:https://blog.csdn.net/raoxiaoya/article/details/97276131