兰博基尼娱乐城|红宝石娱乐城

新聞中心 Case獲取更多行業信息

當前位置:主頁 > 新聞資訊 > 行業新聞 >

java實現微信小程序登錄態維護

日期:2017-10-08 / 人氣:

相信不少喜歡開發的朋友都已經知道微信小程序是個什么物種了,樓主也是從小程序內測期間就開始關注,并且也寫過幾個已經上線的微信小程序。但是基本上都是寫的純前端,最近樓主從后端到前端寫一個完整的小程序項目,中間碰到了一些問題,樓主會找一些個人覺得有學習價值的點不定時的拿出來跟大家分享,希望對你有一些幫助。

    本次就從最基本的微信小程序登錄態維護開始吧。小程序官方api文檔里面有對登錄態的一個完整的解釋,并且有相關的代碼。想看詳情,可以出門右轉:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject我第一次看的時候沒怎么看懂,并且代碼沒有提供java版本的,這讓一個java程序員情何以堪,所以在努力研究了以后決定要做一個java版本的簡單的demo放出來。

    作為服務端,如果想獲得到使用微信小程序的會員信息,就需要小程序作為客戶端把會員的基本信息傳過來。類似于手機號,openId可以作為當前小程序中用戶的唯一性標志。然而如果把會員的openId信息明文直接在服務端與小程序端來回傳輸的話,會有安全性的問題。萬一被別人得到這個openId,就相當于得到會員的手機號一樣,就可以做一些其他操作了,顯然是不安全的。

    為了解決這一問題微信采用了相對安全的方式。

 

				
  1. //app.js
  2. App({
  3. onLaunch: function() {
  4. wx.login({
  5. success: function(res) {
  6. if (res.code) {
  7. //發起網絡請求
  8. wx.request({
  9. url: 'https://test.com/onLogin',
  10. data: {
  11. code: res.code
  12. }
  13. })
  14. } else {
  15. console.log('獲取用戶登錄態失敗!' + res.errMsg)
  16. }
  17. }
  18. });
  19. }
  20. })

微信小程序端會調用wx.login的api,然后會得到一個code,這個code對外人來講是沒有任何意義的,可以放心的傳給服務端。服務端得到code以后,加上你申請小程序時的appId, app secret,去調微信的接口

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code  就可以得到以下參數:

openid 用戶唯一標識  session_key 會話密鑰  unionid 本字段在滿足一定條件的情況下才返回  其中openid 就是會員的唯一性標記,此時服務端可以保存下來。  session_key 以后解密 unionId(整個開放平臺會員的唯一性標識)時有用。

    服務端得到openid以后,為了后邊的交互,要保存下來。一般來講有兩種方式:一種是直接入數據庫,一種是采用效率高一點的緩存。樓主采用的是后者,方式是redis。

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

    也許會有人問,如果有人得到uuid值其實跟得到openid沒什么區別啊,都相當于是會員的唯一性標志。

    所以這里要對這個uuid值進行一個處理。首先存入redis時要有時效性。session_key在微信服務器有效期是30天,建議服務端緩存session_key不超過30天。當小程序傳過來的uuid值過期時,認為這是過期的uuid,則重新走wx.login步驟。

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

    以上就是我理解的整個登錄態的過程,當然還有wx.checkSession這些沒有講到,其實就是發現session_key失效是再重新走一遍上述的流程就可以了。所以沒有仔細說。不知道我有沒有講清楚。我會把整個流程的關鍵代碼貼出來,供大家參考。

 

				
  1. @ActionKey("/loginByWeixin")
  2. public void loginByWeixin() throws Exception {
  3. logger.info("Start getSessionKey");
  4. String json = HttpKit.readData(getRequest());
  5. JSONObject reqJson = JSON.parseObject(json);
  6. String jsCode = reqJson.getString("code");
  7. if (jsCode == null || "".equals(jsCode)) {
  8. logger.info("缺少必要參數");
  9. renderJson(new OutRoot().setCode("100").setMsg(SYS.PARAMETER_FAIL));
  10. } else {
  11. List<Record> record = appInfoService.selectAppInfo();
  12. String appId = record.get(0).get("app_id");
  13. String appSecret = record.get(0).getStr("app_secret");
  14. if (appId == null || "".equals(appId) || appSecret == null || "".equals(appSecret)) {
  15. logger.info("缺少必要參數");
  16. renderJson(new OutRoot().setCode("100").setMsg(SYS.PARAMETER_FAIL));
  17. } else {
  18. String url = "https://api.weixin.qq.com/sns/jscode2session";
  19. String httpUrl = url + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + jsCode
  20. + "&grant_type=authorization_code";
  21. String ret = HttpRequest.sendGetRequest(httpUrl);
  22. logger.info("微信返回的結果 {}", ret);
  23. if (ret == null || "".equals(ret)) {
  24. logger.info("網絡超時");
  25. renderJson(new OutRoot().setCode("101").setMsg(SYS.CONTACT_FAIL));
  26. } else {
  27. JSONObject obj = JSONObject.parseObject(ret);
  28. if (obj.containsKey("errcode")) {
  29. String errcode = obj.get("errcode").toString();
  30. logger.info("微信返回的錯誤碼{}", errcode);
  31. renderJson(new OutRoot().setCode("101").setMsg(SYS.CONTACT_FAIL));
  32. } else if (obj.containsKey("session_key")) {
  33. logger.info("調微信成功");
  34. // 開始處理userInfo
  35. String openId = obj.get("openid").toString();
  36. Record tbMember = new Record();
  37. tbMember.set("weixin_openid", openId);
  38. System.out.println("openId==" + openId);
  39. // 先查詢openId存在不存在,存在不入庫,不存在就入庫
  40. List<Record> memberList = tbMemberService.selectMember(tbMember);
  41. if (memberList != null && memberList.size() > 0) {
  42. logger.info("openId已經存在,不需要插入");
  43. } else {
  44. JSONObject rawDataJson = reqJson.getJSONObject("userInfo");
  45. String nickName = rawDataJson.getString("nickName");
  46. String avatarUrl = rawDataJson.getString("avatarUrl");
  47. String gender = rawDataJson.getString("gender");
  48. String province = rawDataJson.getString("province");
  49. String city = rawDataJson.getString("city");
  50. String country = rawDataJson.getString("country");
  51. tbMember.set("gender", gender);
  52. tbMember.set("nick_name", nickName);
  53. tbMember.set("avatar_url", avatarUrl);
  54. Long openId2 = tbMemberService.addMember(tbMember);
  55. logger.info("openId不存在,插入數據庫");
  56. }
  57. // (1) 獲得sessionkey
  58. String sessionKey = obj.get("session_key").toString();
  59. logger.info("sessionKey==" + sessionKey);
  60. logger.info("openId==" + openId);
  61. // (2) 得到sessionkey以后存到緩存,key值采用不會重復的uuid
  62. String rsession = UUID.randomUUID().toString();
  63. Cache tokenCache = Redis.use("redis_00");
  64. // (3) 首先根據openId,取出來之前存的openId對應的sessionKey的值。
  65. String oldSeesionKey = tokenCache.getJedis().get(openId);
  66. if (oldSeesionKey != null && !"".equals(oldSeesionKey)) {
  67. logger.info("oldSeesionKey==" + oldSeesionKey);
  68. // (4) 刪除之前openId對應的緩存
  69. tokenCache.getJedis().del(oldSeesionKey);
  70. logger.info("老的openId刪除以后==" + tokenCache.getJedis().get(oldSeesionKey));
  71. }
  72. // (5) 開始緩存新的sessionKey: key --> uuid, value --> sessionObj
  73. JSONObject sessionObj = new JSONObject();
  74. sessionObj.put("openId", openId);
  75. sessionObj.put("sessionKey", sessionKey);
  76. tokenCache.getJedis().set(rsession, sessionObj.toJSONString());
  77.  
  78. // (6) 開始緩存新的openId與session對應關系 : key --> openId , value --> rsession
  79. tokenCache.getJedis().set(openId, rsession);
  80.  
  81. String newOpenId = tokenCache.getJedis().get(openId);
  82. String newrSession = tokenCache.getJedis().get(rsession);
  83. logger.info("新的openId==" + newOpenId);
  84. logger.info("新的newrSession==" + newrSession);
  85. // (7) 把新的sessionKey返回給小程序
  86. JSONObject objret = new JSONObject();
  87. objret.put("rdSessionKey", rsession);
  88. objret.put("errno", 0);
  89. renderJson(objret);
  90. }
  91.  
  92. }
  93. }
  94. }
  95. }

    項目框架是我比較喜歡Jfinal,java輕量級急速開發框架,非常高效,也推薦給大家。可能有哪些遺漏的地方歡迎大家積極提出意見和批評。

我是一名java開發者,喜歡研究一些新的技術,體驗一些新的產品,如果喜歡這篇文章,也希望能轉發一下。請注明一下出去就可以了。如果哪里不懂,也可以留言,或者加一下我的個人微信,也希望能交更多的朋友。深圳市靈點網絡科技有限公司是一家專業互聯網品牌營銷顧問機構。專業致力于最前沿的互聯網技術開發和互聯網營銷策劃服務內容涉及企業互聯網咨詢、深圳網站建設深圳網站制作深圳網站設計網頁制作、企業形象設計、包裝畫冊設計、Flash多媒體設計與制作。


編輯:深圳網站建設公司


?
兰博基尼娱乐城 上海天天彩选四历史记录 利物浦队标 塞维利亚vs巴列卡诺 1027期26选5开奖结果 快乐8开奖历史记录 惊喜复活节投注 全民欢乐捕鱼礼包兑换码领取 巴塞罗那大教堂 法兰克福旅游攻略 塞维利亚足球