真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何在小程序中實(shí)現(xiàn)登錄態(tài)管理

這篇“如何在小程序中實(shí)現(xiàn)登錄態(tài)管理”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“如何在小程序中實(shí)現(xiàn)登錄態(tài)管理”文章吧。

在友好等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),全網(wǎng)營銷推廣,外貿(mào)營銷網(wǎng)站建設(shè),友好網(wǎng)站建設(shè)費(fèi)用合理。

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

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

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

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

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

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

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

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

5.攔截器問題,在web項(xiàng)目中,我們會在服務(wù)端給每個(gè)controller寫攔截器,攔截器一般是判斷登錄態(tài),判斷成功則執(zhí)行controller中的代碼,失敗的話,我們一般會重定向到登陸頁面,或者執(zhí)行完登陸代碼后重定向到某個(gè)特定頁面(微信站中這樣做的)。但是這種做法在小程序中是無效的,小程序是動靜分離的,我們不可能從服務(wù)端去重定向到小程序的特定頁面,也不可能從服務(wù)端去調(diào)用小程序的wx.login()方法。所以,我們把這種攔截校驗(yàn)的發(fā)起從服務(wù)端移到小程序端。讓小程序主動發(fā)起這種校驗(yàn),也就是第二點(diǎn)的檢查服務(wù)端登錄態(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)用服務(wù)端的代碼檢查session是否過期(即檢查服務(wù)端的登錄態(tài)),若沒過期則拿到用戶數(shù)據(jù)繼續(xù)執(zhí)行后續(xù)的操作。若過期,則跳4.

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

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

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

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

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

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

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

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

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

1.因?yàn)楹芏囗撁嫘枰〉接脩舻臄?shù)據(jù)才能繼續(xù)操作,所以我們在app.js里面寫一個(gè)getUseInfo方法,供各子頁面調(diào)用,方法如下。

//獲取用戶信息,傳遞的是一個(gè)回調(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ù)是一個(gè)回調(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,還有一個(gè)標(biāo)志位result,用于判斷userInfo緩存數(shù)據(jù)是否失效。

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

 //檢查服務(wù)端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)用服務(wù)端的接口來驗(yàn)證服務(wù)端的session是否已經(jīng)過期,服務(wù)端的代碼如下:

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é)果響應(yīng)給客戶端。

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

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

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

 userLogin: function (cb) {
 const _this = this ;
 wx.login({
 success: function (res) {
  //獲取code然后去訪問服務(wù)端登錄接口,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)用服務(wù)端的登錄代碼。服務(wù)端的登錄偽代碼如下:

public String xcxLogin(){
  Integer result;
  Mapmap= new HashMap();
  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信息響應(yīng)給小程序端
  map.put( "SESSION" , req.getSession().getId()); //將sessionId響應(yīng)給小程序端
  result= 1 ; //登錄操作成功的標(biāo)志位
  } catch (Exception e) {
  e.printStackTrace();
  }
  map.put( "result" , result);
  JSONObject resInfo=JsonUtil.mapToJsonObject(map);
  OutPutMsg.outPutMsg(resInfo.toString()); //將數(shù)據(jù)響應(yīng)給小程序端
  return null ;
 }

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

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

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

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

三.其他注意點(diǎn)

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

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

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

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

四.unionId機(jī)制

如果開發(fā)者擁有多個(gè)移動應(yīng)用、網(wǎng)站應(yīng)用、和公眾帳號(包括小程序),可通過 UnionID 來區(qū)分用戶的唯一性,因?yàn)橹灰峭粋€(gè)微信開放平臺帳號下的移動應(yīng)用、網(wǎng)站應(yīng)用和公眾帳號(包括小程序),用戶的 UnionID 是唯一的。換句話說,同一用戶,對同一個(gè)微信開放平臺下的不同應(yīng)用,unionid是相同的。

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

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

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

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

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

以上就是關(guān)于“如何在小程序中實(shí)現(xiàn)登錄態(tài)管理”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


網(wǎng)頁名稱:如何在小程序中實(shí)現(xiàn)登錄態(tài)管理
鏈接URL:http://weahome.cn/article/jcphed.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部