微信小程序登录状态java后台解密
一、登录流程图
二、微信小程序端
dologin:function(callback = () =>{}){ let that = this; wx.login({ success:function(loginres){ if(loginres){ //获取用户信息 wx.getuserinfo({ withcredentials:true,//非必填 默认为true success:function(infores){ console.log(infores,'>>>'); //请求服务端的登录接口 wx.request({ url: api.loginurl, data:{ code:loginres.code,//临时登录凭证 rawdata:infores.rawdata,//用户非敏感信息 signature:infores.signature,//签名 encryptedata:infores.encrypteddata,//用户敏感信息 iv:infores.iv//解密算法的向量 }, success:function(res){ console.log('login success'); res = res.data; if(res.result==0){ that.globaldata.userinfo = res.userinfo; wx.setstoragesync('userinfo',json.stringify(res.userinfo)); wx.setstoragesync('loginflag',res.skey); console.log("skey="+res.skey); callback(); }else{ that.showinfo('res.errmsg'); } }, fail:function(error){ //调用服务端登录接口失败 // that.showinfo('调用接口失败'); console.log(error); } }); } }); }else{ } } }); }
微信小程序端发起登录请求,携带的参数主要有:
code:loginres.code,//临时登录凭证 rawdata:infores.rawdata,//用户非敏感信息 signature:infores.signature,//签名 encryptedata:infores.encrypteddata,//用户敏感信息 iv:infores.iv//解密算法的向量
需要的数据主要有:
result、userinfo和skey
result用来判断是否登录成功,userinfo是用户的一些信息,保存在缓存中,不用每次都从后台获取,skey是用户登录态标识,也放在缓存中,如果skey存在就直接登录,维护用户的登录状态,具有时效性
三、java后台
@responsebody @requestmapping("/login") public map<string,object> dologin(model model, @requestparam(value = "code",required = false) string code, @requestparam(value = "rawdata",required = false) string rawdata, @requestparam(value = "signature",required = false) string signature, @requestparam(value = "encryptedata",required = false) string encryptedata, @requestparam(value = "iv",required = false) string iv){ log.info( "start get sessionkey" ); map<string,object> map = new hashmap<string, object>( ); system.out.println("用户非敏感信息"+rawdata); jsonobject rawdatajson = json.parseobject( rawdata ); system.out.println("签名"+signature); jsonobject sessionkeyopenid = getsessionkeyoropenid( code ); system.out.println("post请求获取的sessionandopenid="+sessionkeyopenid); string openid = sessionkeyopenid.getstring("openid" ); string sessionkey = sessionkeyopenid.getstring( "session_key" ); system.out.println("openid="+openid+",session_key="+sessionkey); user user = userservice.findbyopenid( openid ); //uuid生成唯一key string skey = uuid.randomuuid().tostring(); if(user==null){ //入库 string nickname = rawdatajson.getstring( "nickname" ); string avatarurl = rawdatajson.getstring( "avatarurl" ); string gender = rawdatajson.getstring( "gender" ); string city = rawdatajson.getstring( "city" ); string country = rawdatajson.getstring( "country" ); string province = rawdatajson.getstring( "province" ); user = new user(); user.setuid( openid ); user.setcreatetime( new date( ) ); user.setsessionkey( sessionkey ); user.setubalance( 0 ); user.setskey( skey ); user.setuaddress( country+" "+province+" "+city ); user.setuavatar( avatarurl ); user.setugender( integer.parseint( gender ) ); user.setuname( nickname ); user.setupdatetime( new date( ) ); userservice.insert( user ); }else { //已存在 log.info( "用户openid已存在,不需要插入" ); } //根据openid查询skey是否存在 string skey_redis = (string) redistemplate.opsforvalue().get( openid ); if(stringutils.isnotblank( skey_redis )){ //存在 删除 skey 重新生成skey 将skey返回 redistemplate.delete( skey_redis ); } // 缓存一份新的 jsonobject sessionobj = new jsonobject( ); sessionobj.put( "openid",openid ); sessionobj.put( "sessionkey",sessionkey ); redistemplate.opsforvalue().set( skey,sessionobj.tojsonstring() ); redistemplate.opsforvalue().set( openid,skey ); //把新的sessionkey和oppenid返回给小程序 map.put( "skey",skey ); map.put( "result","0" ); jsonobject userinfo = getuserinfo( encryptedata, sessionkey, iv ); system.out.println("根据解密算法获取的userinfo="+userinfo); userinfo.put( "balance",user.getubalance() ); map.put( "userinfo",userinfo ); return map; }
获取openid和sessionkey方法
public static jsonobject getsessionkeyoropenid(string code){ //微信端登录code string wxcode = code; string requesturl = "https://api.weixin.qq.com/sns/jscode2session"; map<string,string> requesturlparam = new hashmap<string, string>( ); requesturlparam.put( "appid","你的小程序appid" );//小程序appid requesturlparam.put( "secret","你的小程序appsecret" ); requesturlparam.put( "js_code",wxcode );//小程序端返回的code requesturlparam.put( "grant_type","authorization_code" );//默认参数 //发送post请求读取调用微信接口获取openid用户唯一标识 jsonobject jsonobject = json.parseobject( urlutil.sendpost( requesturl,requesturlparam )); return jsonobject; }
解密用户敏感数据获取用户信息
public static jsonobject getuserinfo(string encrypteddata,string sessionkey,string iv){ // 被加密的数据 byte[] databyte = base64.decode(encrypteddata); // 加密秘钥 byte[] keybyte = base64.decode(sessionkey); // 偏移量 byte[] ivbyte = base64.decode(iv); try { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (keybyte.length % base != 0) { int groups = keybyte.length / base + (keybyte.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; arrays.fill(temp, (byte) 0); system.arraycopy(keybyte, 0, temp, 0, keybyte.length); keybyte = temp; } // 初始化 security.addprovider(new bouncycastleprovider()); cipher cipher = cipher.getinstance("aes/cbc/pkcs7padding","bc"); secretkeyspec spec = new secretkeyspec(keybyte, "aes"); algorithmparameters parameters = algorithmparameters.getinstance("aes"); parameters.init(new ivparameterspec(ivbyte)); cipher.init( cipher.decrypt_mode, spec, parameters);// 初始化 byte[] resultbyte = cipher.dofinal(databyte); if (null != resultbyte && resultbyte.length > 0) { string result = new string(resultbyte, "utf-8"); return json.parseobject(result); } } catch (nosuchalgorithmexception e) { log.error(e.getmessage(), e); } catch (nosuchpaddingexception e) { log.error(e.getmessage(), e); } catch (invalidparameterspecexception e) { log.error(e.getmessage(), e); } catch (illegalblocksizeexception e) { log.error(e.getmessage(), e); } catch (badpaddingexception e) { log.error(e.getmessage(), e); } catch (unsupportedencodingexception e) { log.error(e.getmessage(), e); } catch (invalidkeyexception e) { log.error(e.getmessage(), e); } catch (invalidalgorithmparameterexception e) { log.error(e.getmessage(), e); } catch (nosuchproviderexception e) { log.error(e.getmessage(), e); } return null; }
四、流程
1.小程序端发起请求并携带主要参数
2.java后台接到/login请求后,根据code去调用微信接口获取用户唯一标识openid和sessionkey
3.根据openid查询mysql数据库,判断该用户是否存在,如果不存在将用户非敏感信息和其他初始化数据存入到数据库中,如果已存在,不操作
4.根据openid查询redis数据库,判断openid对应的skey是否存在,如果存在则删除原来老的skey以及对应的openid和sessionkey
5.通过uuid生成唯一的skey,用openid做键,skey做值,存入到redis中
6.然后把skey做键,openid和sessionkey的json串做值也重新存入到redis中
7.根据解密算法,参数有encrypteddata、sessionkey和iv,获取用户信息userinfo,如果userinfo字段不满足需要,可通过userinfo.put( “balance”,user.getubalance() );添加所需要的字段和值
8.将微信小程序需要的数据封装到map中,返回给小程序端
map.put( "skey",skey ); map.put( "result","0" ); map.put( "userinfo",userinfo ); return map;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Java解密微信小程序手机号的方法
下一篇: 动态生成table并实现分页效果心得分享