评论

收藏

[Java] 微信小程序登录状态java后台解密

编程语言 编程语言 发布于:2021-10-06 15:05 | 阅读数:532 | 评论:0

这篇文章主要为大家详细介绍了微信小程序登录状态java后台解密,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
一、登录流程图
DSC0000.jpg

二、微信小程序端
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;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CodeAE代码之家
原文链接:https://blog.csdn.net/qq_38977097/article/details/80778105

关注下面的标签,发现更多相似文章