千家信息网

微信小程序Java登录流程怎么实现

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇"微信小程序Java登录流程怎么实现"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇
千家信息网最后更新 2026年11月03日微信小程序Java登录流程怎么实现

这篇"微信小程序Java登录流程怎么实现"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"微信小程序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//解密算法的向量复制代码

参数解释: code:loginRes.code,//临时登录凭证: 必传 ,通过code来换取后台的 sessionKey和 openId rawData:infoRes.rawData,//用户非敏感信息 signature:infoRes.signature,//签名 encrypteData:infoRes.encryptedData,//用户敏感信息 iv:infoRes.iv//解密算法的向量

signature,//签名、 encryptedData ,//用户敏感信息、 iv //解密算法的向量:

这三个参数是用来解码用户敏感信息的,比如电话号码等信息。

需要的数据主要有: skey ,用于标志用户的唯一性。

三、Java后台

/**     * 登陆接口     */    @RequestMapping("/login")    @ApiResponses({            @ApiResponse(code = 404, message = "服务器未找到资源"),            @ApiResponse(code = 200, message = "请求成功"),            @ApiResponse(code = 500, message = "服务器错误"),            @ApiResponse(code = 401, message = "没有访问权限"),            @ApiResponse(code = 403, message = "服务器拒绝访问"),    })    @ApiOperation(value = "小程序登录", httpMethod = "POST", notes = "小程序登录")    public ResponseEntity login(            @ApiParam(required = true, value = "临时登录凭证code", name = "code") String code,            @ApiParam(required = true, value = "用户非敏感信息", name = "rawData")            @RequestParam(value = "rawData", required = true) String rawData,            @ApiParam(required = true, value = "签名", name = "signature")            @RequestParam(value = "signature", required = true) String signature,            @ApiParam(required = true, value = "用户敏感信息", name = "encrypteData")            @RequestParam(value = "encrypteData", required = true) String encrypteData,            @ApiParam(required = true, value = "解密算法的向量", name = "iv")            @RequestParam(value = "iv", required = true) String iv    ) {        ObjectMapper mapper = new ObjectMapper();        logger.info("signature============================================================="+signature);        logger.info("encrypteData=========================================================="+encrypteData);        logger.info("iv========================================================================"+iv);        RawData data = null;        WxMaJscode2SessionResult session = null;        String openid = null;        String sessionKey = null;        String phoneNumber = null;        try {            if (rawData != null && !"".equals(rawData)) {                //1、获取用户非敏感信息                data = mapper.readValue(rawData, RawData.class);            }            session = this.wxService.getUserService().getSessionInfo(code);            //获取到openid和sessionkey            openid = session.getOpenid();            sessionKey = session.getSessionKey();            logger.info("sessionkey========================================================="+sessionKey);          /*  //2、获取用户手机号            phoneNumber = phone(code, signature, rawData, encrypteData, iv);            logger.info("phoneNumber========================================="+phoneNumber);*/        } catch (IOException e) {            e.printStackTrace();            logger.info("获取用户信息失败");            LoginDataResult loginDataResult = new LoginDataResult();            loginDataResult.setCode("2");            loginDataResult.setMsg("请求失败");            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(loginDataResult);        } catch (WxErrorException e) {            e.printStackTrace();            logger.info("获取用户信息失败");        }        //3、向数据库插入用户信息        String skey = insertUser(data, openid, phoneNumber);        //4、缓存openid, sessionKey, skey到redis        redisCache(openid, sessionKey, skey);        //5、把新的skey返回给小程序        LoginDataResult loginDataResult = new LoginDataResult();        loginDataResult.setSkey(skey);        loginDataResult.setCode("1");        loginDataResult.setMsg("请求成功");        return ResponseEntity.status(HttpStatus.OK).body(loginDataResult);    }    /**     * 缓存openid,sessionKey,skey等信息     * @param openid 小程序用户唯一标志     * @param sessionKey 小程序会话标志     * @param skey 后台生成的用户唯一标志,会话管理     */    private void redisCache(String openid, String sessionKey, String skey) {        //根据openid查询skey是否存在        String skey_redis = jedisClient.hget("WEXIN_USER_OPENID_SKEY", openid);        if (StringUtils.isNotBlank(skey_redis)) {            //存在 删除 skey 重新生成skey 将skey返回            jedisClient.hdel("WEXIN_USER_OPENID_SKEY", openid);            jedisClient.hdel("WEIXIN_USER_SKEY_OPENID", skey_redis);            jedisClient.hdel("WEIXIN_USER_SKEY_SESSIONKEY", skey_redis);        }        //  缓存一份新的        jedisClient.hset("WEXIN_USER_OPENID_SKEY", openid, skey);        jedisClient.expire("WEXIN_USER_OPENID_SKEY",432000);//设置5天过期        jedisClient.hset("WEIXIN_USER_SKEY_OPENID", skey, openid);        jedisClient.expire("WEIXIN_USER_SKEY_OPENID",432000);//设置5天过期        jedisClient.hset("WEIXIN_USER_SKEY_SESSIONKEY", skey, sessionKey);        jedisClient.expire("WEIXIN_USER_SKEY_SESSIONKEY",432000);//设置5天过期    }    /**     * 将用户信息插入到数据库     * @param data 用户信息     * @param openid     * @param phoneNumber 手机号     * @return     */    private String insertUser(RawData data, String openid, String phoneNumber) {        //判断用户数据库是否存在,不存在,入库。        Member user = userService.selectUserByOpenid(openid);        //uuid生成唯一key        String skey = UUID.randomUUID().toString();        if (user == null) {            //入库            user = new Member();            user.setId(skey);            user.setCountry(data.getCountry());            user.setCreatedate(new Date());            user.setDf(1);            user.setGender(data.getGender().equals("1") ? 1 : 2);//1为男,2为女            user.setHeadimg(data.getAvatarUrl());            user.setNickname(data.getNickName());            user.setOpenid(openid);            user.setCitycode(data.getCity());            user.setProvincecode(data.getProvince());            user.setMobileno(phoneNumber);            //插入到数据库            userService.insertUser(user);        } else {            //已存在            logger.info("用户openid已存在,不需要插入");            return user.getId();//返回用户唯一标志skey        }        return skey;    }    /**     * 获取用户板绑定的手机号     * @param sessionKey 小程序session     * @param signature 签名     * @param rawData 用户信息     * @param encryptedData 小程序加密数据     * @param iv 小程序向量     * @return     */    @ApiOperation(value = "用户手机号获取", httpMethod = "GET", notes = "用户手机号获取")    public String phone(String sessionKey, String signature, String rawData, String encryptedData, String iv) {        String phoneNumber = null;        try {            byte[] bytes = WxMiniappUtils.decrypt(Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv), Base64.decodeBase64(encryptedData));            String phone = new String(bytes, "UTF8");            logger.info("phone====================================="+phone);        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (InvalidAlgorithmParameterException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }        return null;    }复制代码

下面对上面代码进行分析:

3.1获取openid和sessionKey
session = this.wxService.getUserService().getSessionInfo(code);//获取到openid和sessionkeyopenid = session.getOpenid();sessionKey = session.getSessionKey();复制代码

这段代码是不是十分的简洁,这里用到了一个 第三方的sdk(weixin-java-tools) ,通过这个sdk可以非常简便的获取到openid和sessionKey,具体的 demo 。

当然,如果你不想用 第三方的sdk ,也可以自己实现,实现代码如下:

public static JSONObject getSessionKeyOrOpenId(String code){    //微信端登录code    String wxCode = code;    String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";    Map requestUrlParam = new HashMap(  );    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;}复制代码
3.2解密用户敏感数据获取用户信息
3.2.1controller

这个部分自己遇到了好多的坑,由于需要获取用户的手机号码,需要解密用户的信息。

/**     * 获取用户板绑定的手机号     * @param sessionKey 小程序session     * @param signature 签名     * @param rawData 用户信息     * @param encryptedData 小程序加密数据     * @param iv 小程序向量     * @return     */    @ApiOperation(value = "用户手机号获取", httpMethod = "GET", notes = "用户手机号获取")    public String phone(String sessionKey, String signature, String rawData, String encryptedData, String iv) {        String phoneNumber = null;        try {            byte[] bytes = WxMiniappUtils.decrypt(Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv), Base64.decodeBase64(encryptedData));            String phone = new String(bytes, "UTF8");            logger.info("phone====================================="+phone);        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (InvalidAlgorithmParameterException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }        return null;    }复制代码
3.2.2decrypt工具类

这里调用了 WxMiniappUtils.decrypt 这个工具类,工具类如下:

/**     * 解密用户手机号算法     * @param sessionkey 小程序登录sessionKey     * @param iv 向量     * @param encryptedData     * @return     * @throws NoSuchPaddingException     * @throws NoSuchAlgorithmException     * @throws InvalidAlgorithmParameterException     * @throws InvalidKeyException     * @throws BadPaddingException     * @throws IllegalBlockSizeException     */    public static byte[] decrypt(byte[] sessionkey, byte[] iv, byte[] encryptedData)            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");        SecretKeySpec keySpec = new SecretKeySpec(sessionkey, "AES");        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);        return cipher.doFinal(encryptedData);    }复制代码

这里用到的 Cipher 类是 javax.crypto 的类。

3.2.3问题

但是这里使用这个 decrypt 工具类的时候,遇到了好多的问题。

第一:AES解密是报错javax.crypto.BadPaddingException: pad block corrupted

这个问题是由于,工具类使用了 Cipher.getInstance("AES/CBC/PKCS5Padding") 。

解决:Cipher cipher = Cipher.getInstance("AES/ECB/ZeroBytePadding");。

第二:java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 这个问题是由于,解码出来的iv不是16位,好像是15位,这个为什么我也不太清楚。

解决:这个怎么解决,自己也没有找到方法,如果有大神解决,望告知!

我的解决方法:其实我发现这个问题并不是这个工具类的问题,我折腾了一天发现,这个工具类并不是不能够解码手机号,有的是可以的,有的解析不到手机号,只有普通的信息,所以我觉得,这个可能是微信用户注册的时候,是不是用手机号注册的,所以会出现有些能够解析,有的不能解析。如果有大神有其他方法,望告知!

3.2.4解析成功数据
{"phoneNumber":"13880684012","purePhoneNumber":"13880684012","countryCode":"86","watermark":{"timestamp":1519460296,"appid":"wx6ede2086ee29a89f"}}复制代码

如果解析到了这样的json数据,说明是成功了的。

3.2.5 另外一种方案
public class AES {    public static final AES instance = new AES();    public static boolean initialized = false;    /**     * AES解密     * @param content 密文     * @return     * @throws InvalidAlgorithmParameterException     * @throws NoSuchProviderException     */    public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {        initialize();        try {            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");            Key sKeySpec = new SecretKeySpec(keyByte, "AES");            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化            byte[] result = cipher.doFinal(content);            return result;        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        } catch (NoSuchProviderException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return null;    }    public static void initialize(){        if (initialized) return;        Security.addProvider(new BouncyCastleProvider());        initialized = true;    }    //生成iv    public static AlgorithmParameters generateIV(byte[] iv) throws Exception{        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");        params.init(new IvParameterSpec(iv));        return params;    }}复制代码
3.2.6第三方sdk方法
WxMaPhoneNumberInfo phoneNoInfo = this.wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);        phoneNumber = phoneNoInfo.getPurePhoneNumber();复制代码

以上就是关于"微信小程序Java登录流程怎么实现"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

用户 信息 程序 登录 代码 手机 手机号 数据 向量 工具 算法 问题 内容 接口 标志 服务 成功 凭证 参数 数据库 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广东万易互联网科技有限公司惠州分公司 江苏根荣互联网科技 以房互联网科技 互联网科技论文 奇士达互联网科技 深圳艾佳互联网科技 无锡溥仪互联网科技有限公司 湖南洣水互联网科技有限公司扣款 中国科技互联网公司收入 广州慧亚互联网科技怎么样 金融科技与互联网金融相同和不同 茂名市互联网科技产业园 宁夏众和广鑫互联网科技有限公司 互联网科技有哪些公司 来此购互联网科技有限公司 爱医互联网络科技 美国互联网科技实力 互联网方面的科技前沿 玉溪新华互联网科技怎么选 互联网科技品牌 互联网科技公司官网 碳银互联网科技 无线互联网科技 伴你行互联网科技有限公司 中国科技互联网公司收入 互联网还是高科技吗 浙南科技城互联网大厦建设工程 佛山市拉法互联网科技有限公司 玉溪新华互联网科技好不好 银行科技岗属于互联网吗
0