最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java實(shí)現(xiàn)微信小程序登錄態(tài)維護(hù)的示例代碼

 更新時(shí)間:2017年09月30日 16:34:59   作者:流浪的家貓  
本篇文章主要介紹了java實(shí)現(xiàn)微信小程序登錄態(tài)維護(hù)的示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下

相信不少喜歡開(kāi)發(fā)的朋友都已經(jīng)知道微信小程序是個(gè)什么物種了,樓主也是從小程序內(nèi)測(cè)期間就開(kāi)始關(guān)注,并且也寫(xiě)過(guò)幾個(gè)已經(jīng)上線的微信小程序。但是基本上都是寫(xiě)的純前端,最近樓主從后端到前端寫(xiě)一個(gè)完整的小程序項(xiàng)目,中間碰到了一些問(wèn)題,樓主會(huì)找一些個(gè)人覺(jué)得有學(xué)習(xí)價(jià)值的點(diǎn)不定時(shí)的拿出來(lái)跟大家分享,希望對(duì)你有一些幫助。

本次就從最基本的微信小程序登錄態(tài)維護(hù)開(kāi)始吧。小程序官方api文檔里面有對(duì)登錄態(tài)的一個(gè)完整的解釋?zhuān)⑶矣邢嚓P(guān)的代碼。想看詳情,可以出門(mén)右轉(zhuǎn):https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject 我第一次看的時(shí)候沒(méi)怎么看懂,并且代碼沒(méi)有提供java版本的,這讓一個(gè)java程序員情何以堪,所以在努力研究了以后決定要做一個(gè)java版本的簡(jiǎn)單的demo放出來(lái)。

作為服務(wù)端,如果想獲得到使用微信小程序的會(huì)員信息,就需要小程序作為客戶端把會(huì)員的基本信息傳過(guò)來(lái)。類(lèi)似于手機(jī)號(hào),openId可以作為當(dāng)前小程序中用戶的唯一性標(biāo)志。然而如果把會(huì)員的openId信息明文直接在服務(wù)端與小程序端來(lái)回傳輸?shù)脑?,?huì)有安全性的問(wèn)題。萬(wàn)一被別人得到這個(gè)openId,就相當(dāng)于得到會(huì)員的手機(jī)號(hào)一樣,就可以做一些其他操作了,顯然是不安全的。

為了解決這一問(wèn)題微信采用了相對(duì)安全的方式。

//app.js
App({
 onLaunch: function() {
  wx.login({
   success: function(res) {
    if (res.code) {
     //發(fā)起網(wǎng)絡(luò)請(qǐng)求
     wx.request({
      url: 'https://test.com/onLogin',
      data: {
       code: res.code
      }
     })
    } else {
     console.log('獲取用戶登錄態(tài)失??!' + res.errMsg)
    }
   }
  });
 }
})

微信小程序端會(huì)調(diào)用wx.login的api,然后會(huì)得到一個(gè)code,這個(gè)code對(duì)外人來(lái)講是沒(méi)有任何意義的,可以放心的傳給服務(wù)端。服務(wù)端得到code以后,加上你申請(qǐng)小程序時(shí)的appId, app secret,去調(diào)微信的接口

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

就可以得到以下參數(shù):

  • openid 用戶唯一標(biāo)識(shí)
  • session_key 會(huì)話密鑰
  • unionid 本字段在滿足一定條件的情況下才返回

其中openid 就是會(huì)員的唯一性標(biāo)記,此時(shí)服務(wù)端可以保存下來(lái)。

session_key 以后解密 unionId(整個(gè)開(kāi)放平臺(tái)會(huì)員的唯一性標(biāo)識(shí))時(shí)有用。

服務(wù)端得到openid以后,為了后邊的交互,要保存下來(lái)。一般來(lái)講有兩種方式:一種是直接入數(shù)據(jù)庫(kù),一種是采用效率高一點(diǎn)的緩存。樓主采用的是后者,方式是redis。

按照微信的建議此時(shí)需要生成一個(gè)不重復(fù)值作為openId的唯一性標(biāo)識(shí)。這里采用的是java的uuid。然后把這個(gè)uuid值作為key,把openid以及后面會(huì)用到的session_key作為value,存進(jìn)redis。并且把uuid值返回給小程序。這樣小程序就可以直接拿uuid值跟服務(wù)端交互。

也許會(huì)有人問(wèn),如果有人得到uuid值其實(shí)跟得到openid沒(méi)什么區(qū)別啊,都相當(dāng)于是會(huì)員的唯一性標(biāo)志。

所以這里要對(duì)這個(gè)uuid值進(jìn)行一個(gè)處理。首先存入redis時(shí)要有時(shí)效性。session_key在微信服務(wù)器有效期是30天,建議服務(wù)端緩存session_key不超過(guò)30天。當(dāng)小程序傳過(guò)來(lái)的uuid值過(guò)期時(shí),認(rèn)為這是過(guò)期的uuid,則重新走wx.login步驟。

為了方便redis中不僅會(huì)寸uuid與openid的對(duì)應(yīng)關(guān)系。還會(huì)再存一條openid對(duì)應(yīng)uuid的記錄,目的是為了下一次重新wx.login步驟時(shí)根據(jù)openid找到之前老的uuid,如果存在的話就刪掉,然后查詢一條新的uuid值,并且把openid對(duì)應(yīng)的這條記錄也更新掉。這樣redis服務(wù)器中就不會(huì)有多余的臟數(shù)據(jù),減輕服務(wù)器的負(fù)擔(dān)。

以上就是我理解的整個(gè)登錄態(tài)的過(guò)程,當(dāng)然還有wx.checkSession這些沒(méi)有講到,其實(shí)就是發(fā)現(xiàn)session_key失效是再重新走一遍上述的流程就可以了。所以沒(méi)有仔細(xì)說(shuō)。不知道我有沒(méi)有講清楚。我會(huì)把整個(gè)流程的關(guān)鍵代碼貼出來(lái),供大家參考。

@ActionKey("/loginByWeixin")
  public void loginByWeixin() throws Exception {
    logger.info("Start getSessionKey");
    String json = HttpKit.readData(getRequest());
    JSONObject reqJson = JSON.parseObject(json);
    String jsCode = reqJson.getString("code");
    if (jsCode == null || "".equals(jsCode)) {
      logger.info("缺少必要參數(shù)");
      renderJson(new OutRoot().setCode("100").setMsg(SYS.PARAMETER_FAIL));
    } else {
      List<Record> record = appInfoService.selectAppInfo();
      String appId = record.get(0).get("app_id");
      String appSecret = record.get(0).getStr("app_secret");
      if (appId == null || "".equals(appId) || appSecret == null || "".equals(appSecret)) {
        logger.info("缺少必要參數(shù)");
        renderJson(new OutRoot().setCode("100").setMsg(SYS.PARAMETER_FAIL));
      } else {
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        String httpUrl = url + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + jsCode
            + "&grant_type=authorization_code";
        String ret = HttpRequest.sendGetRequest(httpUrl);
        logger.info("微信返回的結(jié)果 {}", ret);
        if (ret == null || "".equals(ret)) {
          logger.info("網(wǎng)絡(luò)超時(shí)");
          renderJson(new OutRoot().setCode("101").setMsg(SYS.CONTACT_FAIL));
        } else {
          JSONObject obj = JSONObject.parseObject(ret);
          if (obj.containsKey("errcode")) {
            String errcode = obj.get("errcode").toString();
            logger.info("微信返回的錯(cuò)誤碼{}", errcode);
            renderJson(new OutRoot().setCode("101").setMsg(SYS.CONTACT_FAIL));
          } else if (obj.containsKey("session_key")) {
            logger.info("調(diào)微信成功");
            // 開(kāi)始處理userInfo
            String openId = obj.get("openid").toString();
            Record tbMember = new Record();
            tbMember.set("weixin_openid", openId);
            System.out.println("openId==" + openId);
            // 先查詢openId存在不存在,存在不入庫(kù),不存在就入庫(kù)
            List<Record> memberList = tbMemberService.selectMember(tbMember);
            if (memberList != null && memberList.size() > 0) {
              logger.info("openId已經(jīng)存在,不需要插入");
            } else {
              JSONObject rawDataJson = reqJson.getJSONObject("userInfo");
              String nickName = rawDataJson.getString("nickName");
              String avatarUrl = rawDataJson.getString("avatarUrl");
              String gender = rawDataJson.getString("gender");
              String province = rawDataJson.getString("province");
              String city = rawDataJson.getString("city");
              String country = rawDataJson.getString("country");
              tbMember.set("gender", gender);
              tbMember.set("nick_name", nickName);
              tbMember.set("avatar_url", avatarUrl);
              Long openId2 = tbMemberService.addMember(tbMember);
              logger.info("openId不存在,插入數(shù)據(jù)庫(kù)");
            }
            // (1) 獲得sessionkey
            String sessionKey = obj.get("session_key").toString();
            logger.info("sessionKey==" + sessionKey);
            logger.info("openId==" + openId);
            // (2) 得到sessionkey以后存到緩存,key值采用不會(huì)重復(fù)的uuid
            String rsession = UUID.randomUUID().toString();
            Cache tokenCache = Redis.use("redis_00");
            // (3) 首先根據(jù)openId,取出來(lái)之前存的openId對(duì)應(yīng)的sessionKey的值。
            String oldSeesionKey = tokenCache.getJedis().get(openId);
            if (oldSeesionKey != null && !"".equals(oldSeesionKey)) {
              logger.info("oldSeesionKey==" + oldSeesionKey);
              // (4) 刪除之前openId對(duì)應(yīng)的緩存
              tokenCache.getJedis().del(oldSeesionKey);
              logger.info("老的openId刪除以后==" + tokenCache.getJedis().get(oldSeesionKey));
            }
            // (5) 開(kāi)始緩存新的sessionKey: key --> uuid, value --> sessionObj
            JSONObject sessionObj = new JSONObject();
            sessionObj.put("openId", openId);
            sessionObj.put("sessionKey", sessionKey);
            tokenCache.getJedis().set(rsession, sessionObj.toJSONString());

            // (6) 開(kāi)始緩存新的openId與session對(duì)應(yīng)關(guān)系 : key --> openId , value --> rsession
            tokenCache.getJedis().set(openId, rsession);

            String newOpenId = tokenCache.getJedis().get(openId);
            String newrSession = tokenCache.getJedis().get(rsession);
            logger.info("新的openId==" + newOpenId);
            logger.info("新的newrSession==" + newrSession);
            // (7) 把新的sessionKey返回給小程序
            JSONObject objret = new JSONObject();
            objret.put("rdSessionKey", rsession);
            objret.put("errno", 0);
            renderJson(objret);
          }

        }
      }
    }
  }

項(xiàng)目框架是我比較喜歡Jfinal,java輕量級(jí)急速開(kāi)發(fā)框架,非常高效,也推薦給大家??赡苡心男┻z漏的地方歡迎大家積極提出意見(jiàn)和批評(píng)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringMVC框架如何與Junit整合看這個(gè)就夠了

    SpringMVC框架如何與Junit整合看這個(gè)就夠了

    這篇文章主要介紹了SpringMVC框架如何與Junit整合看這個(gè)就夠了,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 使用java代碼實(shí)現(xiàn)保留小數(shù)點(diǎn)的位數(shù)

    使用java代碼實(shí)現(xiàn)保留小數(shù)點(diǎn)的位數(shù)

    因?yàn)閭€(gè)人應(yīng)用的需要,所以就寫(xiě)個(gè)簡(jiǎn)單點(diǎn)的了。希望大家都給給建議,共同學(xué)習(xí)。需要的朋友也可以參考下
    2013-07-07
  • Java Fluent Mybatis 項(xiàng)目工程化與常規(guī)操作詳解流程篇 下

    Java Fluent Mybatis 項(xiàng)目工程化與常規(guī)操作詳解流程篇 下

    Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。國(guó)內(nèi)又以Mybatis用的多,基于mybatis上的增強(qiáng)框架,又有mybatis plus和TK mybatis等。今天我們介紹一個(gè)新的mybatis增強(qiáng)框架 fluent mybatis關(guān)于項(xiàng)目工程化與常規(guī)操作流程
    2021-10-10
  • Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程

    Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程

    Spring在初始化過(guò)程中,將xml中定義的對(duì)象解析到了BeanDefinition對(duì)象中,我們有必要了解一下BeanDefinition的內(nèi)部結(jié)構(gòu),有助于我們理解Spring的初始化流程
    2022-06-06
  • java生成二維碼并且給二維碼添加logo

    java生成二維碼并且給二維碼添加logo

    這篇文章主要介紹了java生成二維碼并且給二維碼添加logo的實(shí)例代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-12-12
  • java中獲取xml文件的某個(gè)配置節(jié)點(diǎn)內(nèi)容方式

    java中獲取xml文件的某個(gè)配置節(jié)點(diǎn)內(nèi)容方式

    這篇文章主要介紹了java中獲取xml文件的某個(gè)配置節(jié)點(diǎn)內(nèi)容方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Java兩種方式實(shí)現(xiàn)動(dòng)態(tài)代理

    Java兩種方式實(shí)現(xiàn)動(dòng)態(tài)代理

    Java 在 java.lang.reflect 包中有自己的代理支持,該類(lèi)(Proxy.java)用于動(dòng)態(tài)生成代理類(lèi),只需傳入目標(biāo)接口、目標(biāo)接口的類(lèi)加載器以及 InvocationHandler 便可為目標(biāo)接口生成代理類(lèi)及代理對(duì)象。我們稱(chēng)這個(gè)Java技術(shù)為:動(dòng)態(tài)代理
    2020-10-10
  • Servlet實(shí)現(xiàn)文件下載功能

    Servlet實(shí)現(xiàn)文件下載功能

    這篇文章主要為大家詳細(xì)介紹了Servlet實(shí)現(xiàn)文件下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Java多線程程序中synchronized修飾方法的使用實(shí)例

    Java多線程程序中synchronized修飾方法的使用實(shí)例

    synchronized關(guān)鍵字主要北用來(lái)進(jìn)行線程同步,這里我們主要來(lái)演示Java多線程程序中synchronized修飾方法的使用實(shí)例,需要的朋友可以參考下:
    2016-06-06
  • Java執(zhí)行cmd命令的舉例與注意事項(xiàng)

    Java執(zhí)行cmd命令的舉例與注意事項(xiàng)

    Java應(yīng)用程序主要是通過(guò)Runtime和Process兩個(gè)類(lèi)來(lái)執(zhí)行cmd命令,下面這篇文章主要給大家介紹了關(guān)于Java執(zhí)行cmd命令的方法與注意事項(xiàng),文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-02-02

最新評(píng)論

来凤县| 巴青县| 响水县| 襄汾县| 凤山市| 新民市| 仲巴县| 阳新县| 裕民县| 迁西县| 大同县| 郸城县| 武冈市| 汝阳县| 英山县| 花垣县| 辉县市| 永胜县| 古丈县| 伊川县| 滨海县| 榆社县| 托克逊县| 上高县| 南陵县| 杨浦区| 阜阳市| 张家界市| 宜春市| 建湖县| 湘西| 南丹县| 璧山县| 松原市| 伊宁市| 台湾省| 陇西县| 南陵县| 赫章县| 永济市| 菏泽市|