Java服务端--微信小程序登录

本文介绍了如何使用Java实现微信小程序的登录接口,包括处理微信返回的加密数据,进行解密操作,并生成token,以确保用户安全登录。

总得试试

在这里插入图片描述

欢迎所有大佬帮我指正问题!!!!

JAR包

		<dependency>
            <groupId>com.basic</groupId>
            <artifactId>basic-utils</artifactId>
            <version>1.0.17</version>
        </dependency>

实体类

public class WxLoginInfo {

    private String js_code;//小程序登录时获取的code

    private String rawData;//原始数据字符串

    private String  encryptedData;//用户信息的加密数据

    private String signature;//签名

    private String iv;//加密算法的初始向量

    private WxUserInfo wxUserInfo;//用户微信信息

    private String inviteCode;//注册邀请码

    private String phone;//手机号

    private String code;//验证码
    
    private String codeType; //验证码类型:login-登录时、update-修改手机号时、registered-注册

    private String unionId;
    
    private String openId;
    
    /** 微信返回的sessionKey */
    private String sessionKey;  //会话密钥
    
    /** 用户身份 */
    private Object principal;
    
    private String token;
    
    /** 用户输入姓名 */
    private String name;
    private Integer id;
    
    private String nickName;
    private String realName;
    private String avatarUrl;
    /** app类型:android、ios */
    private String appType;
    /** 用户类别:1-客户, 2-合伙人, 3-员工 */
    private Integer userType;
    
    private Integer pageNum;
    private Integer pageSize;
    
    /** 小程序用户ID */
    private Integer miniUserId;
    /** 报备类型:2-带看中 3-认购中 4-已购房 5-对佣 */
    private Integer repostType;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public String getCodeType() {
		return codeType;
	}

	public void setCodeType(String codeType) {
		this.codeType = codeType;
	}
    
	public Object getPrincipal() {
		return principal;
	}

	public void setPrincipal(Object principal) {
		this.principal = principal;
	}

	public String getOpenId() {
		return openId;
	}

	public void setOpenId(String openId) {
		this.openId = openId;
	}

	public String getSessionKey() {
		return sessionKey;
	}

	public void setSessionKey(String sessionKey) {
		this.sessionKey = sessionKey;
	}

	public WxUserInfo getWxUserInfo() {
        return wxUserInfo;
    }

    public void setWxUserInfo(WxUserInfo wxUserInfo) {
        this.wxUserInfo = wxUserInfo;
    }

    public String getJs_code() {
        return js_code;
    }

    public void setJs_code(String js_code) {
        this.js_code = js_code;
    }

    public String getInviteCode() {
        return inviteCode;
    }

    public void setInviteCode(String inviteCode) {
        this.inviteCode = inviteCode;
    }

    public String getEncryptedData() {
        return encryptedData;
    }

    public void setEncryptedData(String encryptedData) {
        this.encryptedData = encryptedData;
    }

    public String getIv() {
        return iv;
    }

    public void setIv(String iv) {
        this.iv = iv;
    }

    public String getRawData() {
        return rawData;
    }

    public void setRawData(String rawData) {
        this.rawData = rawData;
    }

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

	public String getUnionId() {
		return unionId;
	}

	public void setUnionId(String unionId) {
		this.unionId = unionId;
	}

}

public class WxUserInfo {

    private String nickName;
    private String avatarUrl;
    private String country;
    private String province;
    private String city;
    private String language;
    private Byte gender;

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getAvatarUrl() {
        return avatarUrl;
    }

    public void setAvatarUrl(String avatarUrl) {
        this.avatarUrl = avatarUrl;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public Byte getGender() {
        return gender;
    }

    public void setGender(Byte gender) {
        this.gender = gender;
    }
}

登录接口

/**
     * @Description //TODO 微信登录
     * @Date 14:08 2021/5/24
     * @Param [code, APPID, APPSecret]
     * @return com.pdw.common.ResponseResult
     **/
    @RequestMapping("/wxLogin")
    @ResponseBody
    public ResponseResult wxLogin(@RequestBody WxLoginInfo wxLoginInfo) {
        String APPSecret = "";
        String APPID = "";
        String jsCode = wxLoginInfo.getJs_code();

        if (jsCode == null /*|| wxUserInfo == null*/) {
            return  ResponseUtil.error(ResponseCodeEnum.PARA_ERROR);
        }

        log.info("微信登录信息appId:{},appSecret:{},jsCode:{}",APPID, APPSecret, jsCode);
        WxMini.Session wxSession= WxMini.jscode2session(APPID, APPSecret, jsCode);
        String sessionKey = wxSession.getSession_key();
        String openId = wxSession.getOpenid();
        log.info("微信登录返回信息sessionKey:{},openId:{},unionid:{}", sessionKey, openId, wxSession.getUnionid());
        if (StringUtils.isBlank(sessionKey)|| StringUtils.isBlank(openId)) {
            return  ResponseUtil.error(ResponseCodeEnum.FAIL.getCode(),"微信登陆失败");
        }

        //新用户第一次登陆获取不到unionid
        String unionid = wxSession.getUnionid();
        String phone = wxLoginInfo.getPhone();
        {
            String s = JSONObject.toJSONString(wxLoginInfo);
            log.warn(s);
        }
        log.info("微信注册信息encryptedData{},iv:{}", wxLoginInfo.getEncryptedData(), wxLoginInfo.getIv());
        if (wxLoginInfo.getEncryptedData()!= null) {
            //if (WxMini.checkSignature(wxLoginInfo.getRawData(), sessionKey, wxLoginInfo.getSignature())) {
            JSONObject info = getUserInfo(wxLoginInfo.getEncryptedData(), sessionKey, wxLoginInfo.getIv());
            if(info == null){
                return  ResponseUtil.error(ResponseCodeEnum.FAIL.getCode(),"微信登录失败");
            }
            log.info("解密微信注册信息info:{}", info.toJSONString());
            if(org.apache.commons.lang.StringUtils.isBlank(unionid)){
                unionid = info.getString("unionId");
            }
            if(org.apache.commons.lang.StringUtils.isBlank(phone)){
                phone = info.getString("phoneNumber");
            }
            //}
        }
        if (org.apache.commons.lang.StringUtils.isBlank(phone)) {
            return  ResponseUtil.error(ResponseCodeEnum.FAIL.getCode(),"获取手机号失败");
        }

        //判断手机号是否首次登录
        UserInfo userInfo = userInfoService.findByPhone(phone);
        if(userInfo == null){
            userInfo = new UserInfo();
            userInfo.setUserName(phone);
            userInfo.setPhone(phone);
            userInfo.setStatus(0);
            userInfo.setCreateTime(LocalDateTime.now());
            userInfo.setIsDelete(0);
            userInfo.setUserType(1);
            userInfoService.insert(userInfo);
        }

        String token = generateToken(userInfo.getId(), "wx");
        Map<String, Object> result = new HashMap<>();

        result.put("token", token);
        result.put("userInfo", userInfo);
        return ResponseUtil.success(result);
    }


    /**
     *  @param userInfo
     * @description:更新微信用户信息
     * @return
     */
    @RequestMapping(value = "/mini/loginInfo")
    @ResponseBody
    public ResponseResult wxLoginInfo(@RequestBody WxUserInfo userInfo, @RequestHeader("userId")Integer userId) {
        if (userInfo == null) {
            return  ResponseUtil.error(ResponseCodeEnum.PARA_ERROR);
        }
        UserInfo user = userInfoService.findById(userId);
        UserInfo us = new UserInfo();
        if(!org.apache.commons.lang.StringUtils.isBlank(userInfo.getNickName())){
            us.setUserName(filterEmoji(userInfo.getNickName()));
        }
        if(!org.apache.commons.lang.StringUtils.isBlank(userInfo.getAvatarUrl())){
            us.setLogo(userInfo.getAvatarUrl());
        }
        us.setId(userId);
        us.setUpdateTime(LocalDateTime.now());
        userInfoService.update(us);
        user.setPassword(null);

        return  ResponseUtil.success(user);
    }

    /**
     * 对微信用户的昵称进行Emoji表情过滤
     * @param source
     * @return
     */
    public static String filterEmoji(String source) {
        if(org.apache.commons.lang.StringUtils.isNotBlank(source)){
            return source.replaceAll("[\\ud800\\udc00-\\udbff\\udfff\\ud800-\\udfff]", "*");
        }else{
            return source;
        }
    }

微信数据解密

//微信数据解密
    public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv){
        // 被加密的数据
        byte[] dataByte = WxMini.decodeBase64(encryptedData);
        // 加密秘钥
        byte[] keyByte = WxMini.decodeBase64(sessionKey);
        // 偏移量
        byte[] ivByte = WxMini.decodeBase64(iv);
        log.error("微信加密数据:{},{},{}",dataByte, keyByte, ivByte);
        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/PKCS5Padding");
            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 JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            log.error("微信数据解密失败:{}",e);
            e.printStackTrace();
        }
        return null;
    }

生成token

//生成token
    public String generateToken(Integer userId, String source) {
        //生成token
        String token = source + UUID.randomUUID().toString().replaceAll("-", "");
        Boolean flag = stringRedisTemplate.hasKey(token);
//        while (redisUtil.hasKey(token)) {
        while (flag) {
            token = UUID.randomUUID().toString().replaceAll("-", "");
        }
        //存储redis里
        String tokenKey = RedisPreKey.K.TOKEN_USER.to(source, token);
//        redisUtil.set(tokenKey, String.valueOf(userId), tokenExpireTime);
        stringRedisTemplate.opsForValue().set(tokenKey, String.valueOf(userId), 108000, TimeUnit.SECONDS);
        return token;
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值