当前位置: 移动技术网 > IT编程>开发语言>Java > 微信小程序登录状态java后台解密

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

2019年07月19日  | 移动技术网IT编程  | 我要评论

条纹潜鱼,李小璐的胸部,抢婴门

一、登录流程图

二、微信小程序端

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;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网