怎么在小程序中實現(xiàn)登錄態(tài)管理

今天就跟大家聊聊有關怎么在小程序中實現(xiàn)登錄態(tài)管理,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

成都創(chuàng)新互聯(lián)服務項目包括師宗網(wǎng)站建設、師宗網(wǎng)站制作、師宗網(wǎng)頁制作以及師宗網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,師宗網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到師宗省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

一.小程序的登錄態(tài)

要明白小程序跟傳統(tǒng)的web項目的不同之處在于它不依托于瀏覽器,所以它沒有cookie,自然無法用session來管理登錄態(tài)。這給我們的編碼造成了不小麻煩。但是其實我們可以通過在請求頭中加入鍵為JESSIONID(或者SESSION),值為sessionId的cookie來模擬這種操作。同時在服務端響應給小程序的時候,若sessionId有發(fā)生變化則再回傳給客戶端。

還有一個要注意的是,小程序也有自己的登錄態(tài),那就是session_key的生命周期,session_key是小程序中為了加密數(shù)據(jù)而提供的一個密鑰,具有一定的生命周期。查看小程序官方文檔,可以知道它是在服務端調(diào)用code2Session獲取的??梢酝ㄟ^小程序的wx.checkSession()來校驗小程序端的登錄態(tài)是否過期。

弄清楚了上述兩點,我們的要解決的問題包括。

1.校驗小程序的登錄態(tài)

2.校驗服務端的登錄態(tài),即是否能從session中拿到用戶數(shù)據(jù)。

3.任何一方的登錄態(tài)過期,都調(diào)用登陸的相關代碼,注意登陸的相關代碼包含小程序端和服務端。后續(xù)會說。

4.用戶信息如何儲存。在web項目里,我們是將用戶信息存放在session里,這樣在服務端就可以直接用,而借助jsp的某些標簽,在jsp頁面我們也可以直接從session中拿出用戶數(shù)據(jù)。但現(xiàn)在是小程序,在服務端我們依然可以從session中獲取用戶數(shù)據(jù),但是在客戶端,必須等待服務端的回傳。這樣每次請求都響應用戶數(shù)據(jù)的做法顯然不是很合理的,所以我們可以將用戶數(shù)據(jù)保存在微信的緩存里。

5.攔截器問題,在web項目中,我們會在服務端給每個controller寫攔截器,攔截器一般是判斷登錄態(tài),判斷成功則執(zhí)行controller中的代碼,失敗的話,我們一般會重定向到登陸頁面,或者執(zhí)行完登陸代碼后重定向到某個特定頁面(微信站中這樣做的)。但是這種做法在小程序中是無效的,小程序是動靜分離的,我們不可能從服務端去重定向到小程序的特定頁面,也不可能從服務端去調(diào)用小程序的wx.login()方法。所以,我們把這種攔截校驗的發(fā)起從服務端移到小程序端。讓小程序主動發(fā)起這種校驗,也就是第二點的檢查服務端登錄態(tài)。

二.小程序登錄態(tài)的方案

經(jīng)過上面的分析,我們整理出小程序登錄態(tài)的方案。

1.在需要用戶登錄態(tài)的頁面,首先從緩存中獲取用戶數(shù)據(jù)userInfo,若無數(shù)據(jù),則跳4

2.調(diào)用wx.checkSession()檢查小程序端的登錄態(tài)是否過期,若沒過期,跳3,若過期,跳4

3.調(diào)用服務端的代碼檢查session是否過期(即檢查服務端的登錄態(tài)),若沒過期則拿到用戶數(shù)據(jù)繼續(xù)執(zhí)行后續(xù)的操作。若過期,則跳4.

4.登錄操作,登錄操作分為如下幾個步驟。

--a.小程序端調(diào)用wx.login()接口得到code。(code只能使用一次)

--b.服務端利用這個code訪問code2Session接口得到session_key和open_id,并將session_key和open_id存入到session中。

--c.服務端執(zhí)行登錄操作,主要是通過open_id去數(shù)據(jù)庫中尋找用戶數(shù)據(jù),若無則新增用戶到數(shù)據(jù)庫,若有則取出用戶數(shù)據(jù)。

--d.將用戶數(shù)據(jù)userInfo,session_key,open_id等數(shù)據(jù)都存放到session中,方便服務端下次拿。

--e.將用戶數(shù)據(jù)userInfo,連同session的sessionId一起響應給小程序端。

--f.小程序端得到用戶數(shù)據(jù)和userInfo后更新緩存中的userInfo(包括JESSIONID的值sessionId)

上述過程可以用微信官方的這張圖來表示。

怎么在小程序中實現(xiàn)登錄態(tài)管理

這邊的自定義登錄態(tài)就是sessionId,自定義登錄態(tài)與session_key,openid關聯(lián)就是將session_key,openid存入到session中。

下面我們來看具體的代碼吧。

1.因為很多頁面需要取到用戶的數(shù)據(jù)才能繼續(xù)操作,所以我們在app.js里面寫一個getUseInfo方法,供各子頁面調(diào)用,方法如下。

//獲取用戶信息,傳遞的是一個回調(diào)函數(shù),獲取到用戶信息后執(zhí)行回調(diào)函數(shù),傳入的參數(shù)是userInfo
 getUserInfo: function (cb) {
 const _this = this ;
 wx.checkSession({
 success: function () {
  let userInfo = wx.getStorageSync( 'userInfo' ); //先從內(nèi)存中獲取userInfo
  if (userInfo.result == 1 ) {
  _this.refreshSession(cb);
  } else {
  _this.userLogin(cb);
  }
 },
 fail: function () {
  _this.userLogin(cb);
 }
 })
 },

上述方法的參數(shù)是一個回調(diào)函數(shù),不同的頁面在獲取了userInfo以后傳入不同的回調(diào)函數(shù),回調(diào)函數(shù)的參數(shù)就是要獲取的userInfo。

首先,調(diào)用wx.checkSession()方法判定小程序端登錄態(tài)是否失效,失效的話則去執(zhí)行userLogin(cb)操作,未失效則從緩存中去拿userInfo數(shù)據(jù)。在userInfo中,我們主要存放的是userName,userFace等用戶數(shù)據(jù)和SESSION,還有一個標志位result,用于判斷userInfo緩存數(shù)據(jù)是否失效。

然后,如果我們能從緩存中拿到用戶數(shù)據(jù),就要 檢驗服務端的登錄態(tài)是否通過。訪問refreshSession(cb)方法。代碼如下

 //檢查服務端session是否過期
 refreshSession: function (cb) {
 const _this = this ;
 let userInfo = wx.getStorageSync( 'userInfo' );
 wx.request({
 url: _this.domain + _this.api.xcxCheckSessionReq,
 method: 'GET' ,
 header: {
  'Cookie' : 'JSESSIONID=' + userInfo.SESSION + ';SESSION=' + userInfo.SESSION,
 },
 success: function (res) {
  if (res.data == 1) {
  _this.globalData.userInfo = userInfo;
  typeof cb == "function" && cb(_this.globalData.userInfo);
  } else {
  wx.removeStorageSync( 'userInfo' );
  _this.userLogin(cb);
  }
 },
 fail: function () {
  wx.removeStorageSync( 'userInfo' );
  _this.userLogin(cb);
 }
 })
 },

此處,調(diào)用服務端的接口來驗證服務端的session是否已經(jīng)過期,服務端的代碼如下:

public String xcxCheckSession() {
  Integer result;
  HttpServletRequest req = ServletActionContext.getRequest();
  HttpSession s = req.getSession();
  if (s.getAttribute( "c_userId" )!= null ){
  result=1;
  } else {
  result=0;
  }
  OutPutMsg.outPutMsg(result.toString());
  return null ;
 }

其中OutPutMsg方法就是將結(jié)果響應給客戶端。

上述代碼根據(jù)小程序端傳過來的JSESSIONID或者SESSION的值,利用servlet的特性,根據(jù)這個值去獲取session,再判斷session中是否有用戶信息。從而完成服務端的登錄態(tài)校驗。其實原理跟我們在服務端使用攔截器校驗session是否過期是一樣的。

若服務端登錄態(tài)校驗失敗,則需要清空緩存中的userInfo信息,然后去執(zhí)行userLogin(cb)方法,進行登錄。

2.登錄操作涉及到小程序端和服務端,小程序端的代碼如下:

 userLogin: function (cb) {
 const _this = this ;
 wx.login({
 success: function (res) {
  //獲取code然后去訪問服務端登錄接口,code主要是為了換openId和session_key。
  if (res.code) {
  wx.request({
  url: _this.domain + _this.api.loginCheckReq,
  method: 'POST' ,
  header: {
  'Content-Type' : _this.globalData.postHeader
  },
  data: {
  jsCode: res.code,
  },
  success: function (res) {
  //登錄成功
  if (res.data.result == 1) {
   wx.getUserInfo({
   withCredentials: true ,
   success: function (result) {
   res.data.wechatUserInfo = result.userInfo;
   _this.globalData.userInfo = res.data;
   _this.globalData.userInfo.face = '/uploadFiles/' + res.data.userFace;
   typeof cb == "function" && cb(_this.globalData.userInfo)
   wx.setStorageSync( 'userInfo' , _this.globalData.userInfo); //將用戶數(shù)據(jù)存入內(nèi)存
   },
   fail: function () {
   _this.globalData.userInfo = res.data;
   _this.globalData.userInfo.face = res.data.prefix + '/uploadFiles/' + res.data.userFace;
   typeof cb == "function" && cb(_this.globalData.userInfo)
   wx.setStorageSync( 'userInfo' , _this.globalData.userInfo);
   }
   })
  }
  }
  })
  }
 }
 })
 },

首先小程序端訪問wx.login()接口獲取code,然后調(diào)用服務端的登錄代碼。服務端的登錄偽代碼如下:

public String xcxLogin(){
  Integer result;
  Map<String,Object>map= new HashMap<String, Object>();
  try {
  HttpServletRequest req = ServletActionContext.getRequest();
  String jsCode = req.getParameter( "jsCode" );
  String url = "https://api.weixin.qq.com/sns/jscode2session?appid="
   + ConfigUtil.XCX_APP_ID + "&secret="
   + ConfigUtil.XCX_APP_SECRET + "&js_code=" + jsCode
   + "&grant_type=authorization_code" ;
  String urlDetail = URLConnectionUtil.getUrlDetail(url); //訪問小程序接口,獲取openId,session_key
  JSONObject jsonObject = JSONObject.fromObject(urlDetail);
  String openId=jsonObject.getString( "openid" );
  String session_key=jsonObject.getString( "session_key" );
  TUser user=getUserByOpenId(openId);
  if (user== null ){
   //新增用戶,插入到數(shù)據(jù)庫
   TUser userTmp= new TUser();
   user.setOpenId(openId);
   addUser(userTmp);
   user=userTmp;
  }
  session.put( "user" , user); //將user信息放入session
  session.put( "session_key" , session_key); //將session_key放入session
  map.put( "user" , user); //將user信息響應給小程序端
  map.put( "SESSION" , req.getSession().getId()); //將sessionId響應給小程序端
  result= 1 ; //登錄操作成功的標志位
  } catch (Exception e) {
  e.printStackTrace();
  }
  map.put( "result" , result);
  JSONObject resInfo=JsonUtil.mapToJsonObject(map);
  OutPutMsg.outPutMsg(resInfo.toString()); //將數(shù)據(jù)響應給小程序端
  return null ;
 }

先根據(jù)code去拿到openId和session_key,然后從數(shù)據(jù)庫去查詢是否有這個openId的客戶,沒有的話直接執(zhí)行新增操作,然后將user信息(包含openId)和session_key信息存入session,方便服務端下次直接獲取。再把user信息和sessionId回傳給小程序端。

小程序端拿到這些信息,就可以把他們緩存起來,以備下次使用啦。

3.最后,凡事需要用戶登錄才能進入的頁面,我們都讓他調(diào)用getUserInfo(cb),并傳入cb回調(diào)方法,比如。

 onShow: function () {
 const _this = this ;
 app.getUserInfo( function (userInfo) {
 _this.setData({
  userInfo: userInfo,
 })
 });
 },

三.其他注意點

關于上述代碼的userLogin()部分,目前主流的有兩種。

1.使用wx.login()靜默授權,獲取用戶的openId(),不要求用戶綁定手機號,只在涉及到需要用戶手機號的時候才讓用戶來綁定手機號。只需要在userInfo中預留一個標記用戶是否有綁定手機號的字段即可。本文介紹的是采用這種登錄方式。

2.必須要用戶登錄輸入手機號及驗證碼才算登錄成功,則將userLogin處的邏輯改為跳轉(zhuǎn)至登錄頁面。然后服務端的判斷邏輯則改為通過手機號和驗證碼來確認用戶是否登錄成功。其他部分的邏輯不變,這也是目前比較主流的做法

3:可以簡單的理解wx.login()接口是靜默授權,它能得到用戶的openId;而wx.getUserInfo()需要用戶授權,可以獲取到用戶的頭像,昵稱等信息。還可以通過wx.getUserInfo()獲取到unionId等私密信息,但是必須得在已經(jīng)調(diào)用過wx.login()且登錄態(tài)尚未過期的前提下。

四.unionId機制

如果開發(fā)者擁有多個移動應用、網(wǎng)站應用、和公眾帳號(包括小程序),可通過 UnionID 來區(qū)分用戶的唯一性,因為只要是同一個微信開放平臺帳號下的移動應用、網(wǎng)站應用和公眾帳號(包括小程序),用戶的 UnionID 是唯一的。換句話說,同一用戶,對同一個微信開放平臺下的不同應用,unionid是相同的。

綁定了開發(fā)者帳號的小程序,可以通過下面 4 種途徑獲取 UnionID。

1.調(diào)用接口 wx.getUserInfo,從解密數(shù)據(jù)中獲取 UnionID。注意本接口需要用戶授權,請開發(fā)者妥善處理用戶拒絕授權后的情況。

2.如果開發(fā)者帳號下存在同主體的公眾號,并且該用戶已經(jīng)關注了該公眾號。開發(fā)者可以直接通過 wx.login + code2Session 獲取到該用戶 UnionID,無須用戶再次授權。

3.如果開發(fā)者帳號下存在同主體的公眾號或移動應用,并且該用戶已經(jīng)授權登錄過該公眾號或移動應用。開發(fā)者也可以直接通過 wx.login + code2Session 獲取到該用戶 UnionID ,無須用戶再次授權。

4.小程序端調(diào)用云函數(shù)時,當滿足 UnionID 獲取條件時可在云函數(shù)中通過 cloud.getWXContext 獲取 UnionID

看完上述內(nèi)容,你們對怎么在小程序中實現(xiàn)登錄態(tài)管理有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

名稱欄目:怎么在小程序中實現(xiàn)登錄態(tài)管理
當前路徑:http://bm7419.com/article16/jciddg.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供面包屑導航、網(wǎng)站排名、小程序開發(fā)、用戶體驗、做網(wǎng)站、服務器托管

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設計