扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
利用java实现一个微信小程序登录态维护功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
公司主营业务:成都做网站、网站制作、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出仲巴免费做网站回馈大家。
作为服务端,如果想获得到使用微信小程序的会员信息,就需要小程序作为客户端把会员的基本信息传过来。类似于手机号,openId可以作为当前小程序中用户的唯一性标志。然而如果把会员的openId信息明文直接在服务端与小程序端来回传输的话,会有安全性的问题。万一被别人得到这个openId,就相当于得到会员的手机号一样,就可以做一些其他操作了,显然是不安全的。
为了解决这一问题微信采用了相对安全的方式。
//app.js App({ onLaunch: function() { wx.login({ success: function(res) { if (res.code) { //发起网络请求 wx.request({ url: 'https://test.com/onLogin', data: { code: res.code } }) } else { console.log('获取用户登录态失败!' + res.errMsg) } } }); } })
微信小程序端会调用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以后,为了后边的交互,要保存下来。一般来讲有两种方式:一种是直接入数据库,一种是采用效率高一点的缓存。楼主采用的是后者,方式是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失效是再重新走一遍上述的流程就可以了。所以没有仔细说。不知道我有没有讲清楚。我会把整个流程的关键代码贴出来,供大家参考。
@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("缺少必要参数"); renderJson(new OutRoot().setCode("100").setMsg(SYS.PARAMETER_FAIL)); } else { Listrecord = 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("缺少必要参数"); 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("微信返回的结果 {}", ret); if (ret == null || "".equals(ret)) { logger.info("网络超时"); 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("微信返回的错误码{}", errcode); renderJson(new OutRoot().setCode("101").setMsg(SYS.CONTACT_FAIL)); } else if (obj.containsKey("session_key")) { logger.info("调微信成功"); // 开始处理userInfo String openId = obj.get("openid").toString(); Record tbMember = new Record(); tbMember.set("weixin_openid", openId); System.out.println("openId==" + openId); // 先查询openId存在不存在,存在不入库,不存在就入库 List memberList = tbMemberService.selectMember(tbMember); if (memberList != null && memberList.size() > 0) { logger.info("openId已经存在,不需要插入"); } 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不存在,插入数据库"); } // (1) 获得sessionkey String sessionKey = obj.get("session_key").toString(); logger.info("sessionKey==" + sessionKey); logger.info("openId==" + openId); // (2) 得到sessionkey以后存到缓存,key值采用不会重复的uuid String rsession = UUID.randomUUID().toString(); Cache tokenCache = Redis.use("redis_00"); // (3) 首先根据openId,取出来之前存的openId对应的sessionKey的值。 String oldSeesionKey = tokenCache.getJedis().get(openId); if (oldSeesionKey != null && !"".equals(oldSeesionKey)) { logger.info("oldSeesionKey==" + oldSeesionKey); // (4) 删除之前openId对应的缓存 tokenCache.getJedis().del(oldSeesionKey); logger.info("老的openId删除以后==" + tokenCache.getJedis().get(oldSeesionKey)); } // (5) 开始缓存新的sessionKey: key --> uuid, value --> sessionObj JSONObject sessionObj = new JSONObject(); sessionObj.put("openId", openId); sessionObj.put("sessionKey", sessionKey); tokenCache.getJedis().set(rsession, sessionObj.toJSONString()); // (6) 开始缓存新的openId与session对应关系 : 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); } } } } }
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注创新互联行业资讯频道,感谢您对创新互联的支持。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流