微信小程序获取手机号授权登录java代码

微信小程序授权登录java代码

微信小程序授权登录java代码

微信小程序登录和普通后台系统登录不一样,因为这并不是你输入账户密码然后点击登录就登录了,而是通过微信授权,去换取openid,session_key进行唯一标识确定和获取微信用户数据。
微信小程序前端请参考链接: 微信小程序前端登录.
微信授权登录流程图
在这里插入图片描述
话不多说,现在上后端代码 特别注意解密的时候用post请求不然会有转义字符而导致解密失败
yml 配置

weixin:
  appid: '你们公司的appid'
  secret: '你们公司的secret'
  access-token-base-url: 'https://api.weixin.qq.com/sns/jscode2session?'

        <!-- 解密微信小程序data-->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.57</version>
        </dependency>
   @Autowired
    WxUserService wxUserService;
    // private String phoneCode="";
    @Value("${weixin.appid}")
    private  String appid;

    @Value("${weixin.secret}")
    private  String secret;

    @Value("${weixin.access-token-base-url}")
    private  String wxAccessTokenBaseUrl;
    @Autowired
    WxUserMapper wxUserMapper;

    @Autowired
    JwtProcessor jwt;

    /**
     *  授权
     * @return
     */
    @GetMapping("/auth")
    public JSONObject loginAppkey(WxUserModel wxUser,HttpServletResponse resp) throws UploaderTypeNotExistException, IOException, FileMetaNotValidException {
        Assert.notNull(wxUser.getCode(),"code不能为空");
        JSONObject jsonObject = new JSONObject();
        RestTemplate restTemplate = new RestTemplate();
        String url = wxAccessTokenBaseUrl+"appid="+appid+"&secret="+secret+"&js_code="+wxUser.getCode()+"&grant_type=authorization_code";
        ResponseEntity forEntity1 = restTemplate.getForEntity(url, String.class);
        JSONObject parse = JSONObject.parseObject(forEntity1.getBody().toString());
        // parse解析出errcode说明code已经过期
        Assert.isNull(parse.get("errcode"),"临时code无效!");
        /** 这里看数据库有没有存openid如果存在则直接登录,如果没有则将session_key和openid返给小程序,
       如果你的小程序只是不需要绑定手机号则下面快捷登录的不需要,你只需要把唯一凭证openid存入数据库然
       后给前端 返个token就OK了
       */
        WxUserModel openid = wxUserMapper.selectOpenid(parse.get("openid").toString());
        // 存在openid直接登录
        if(openid!=null){
            UserIdentity ui = new UserIdentity();
            ui.setAccountName(openid.getPhone());
            String token = jwt.generateToken(ui);
            resp.setHeader("Authorization", token);
            jsonObject.put("wx",openid);
        }else{
            jsonObject.put("wx",parse);
        }
        return jsonObject;
    }

    /**
     * 快捷登录 这相当于注册,将用户信息保存到数据库
     * @param sessionKey  这个是微信小程序端传code的时候通过请求微信服务器会生成的一个sessionkey和openid,这里传是为了后面解码用户信息要用到
     * @param openid 这个是为了确定用户唯一标识
     * @param encryptedData 小程序获取用户信息加密信息比如手机号..
     * @param vi 小程序加密信息
  
     * @return
     */
    @PostMapping("/quickLogin")
    public JSONObject login(String sessionKey,String vi,String encryptedData,String openid,HttpServletResponse resp) throws IOException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("wu",wxUserService.addWXuser(wxUser,resp));
        return jsonObject;
    }

service层

  /**
     * 添加微信用户信息
     * @param wxUserModel
     */
    public WxUserModel addWXuser(WxUserModel wxUserModel,HttpServletResponse resp) throws IOException {
        WxUserModel wu = null;
        // 查看openid是否存在
        wu = wxUserMapper.selectOpenid(wxUserModel.getOpenid());
        if(wu==null){
        // 这里通过解码之前小程序传过来的加密数据进行解密,获取微信用户的数据
            JSONObject s = WechatDecryptDataUtil.getPhoneNumber(wxUserModel.getSessionKey(),wxUserModel.getEncryptedData(),  wxUserModel.getVi());
            String phoneNumber = s.get("phoneNumber").toString();
            WxUserModel w = wxUserMapper.selectPhone(phoneNumber);
            Assert.isNull(w,"该手机号已绑定,请换手机号");
            wu = new WxUserModel();
            wu.setOpenid(wxUserModel.getOpenid());
            wu.setPhone(phoneNumber);
            wxUserMapper.insert(wu);
        }
        UserIdentity ui = new UserIdentity();
        ui.setAccountName(wu.getPhone());
        String token = jwt.generateToken(ui);
        resp.setHeader("Authorization", token);
        return wu;
    }

解码工具类

package util;

import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;

public class WechatDecryptDataUtil {

    //解析电话号码
    public static JSONObject getPhoneNumber(String session_key, String encryptedData, String iv) throws IOException {
        System.out.println(session_key);
        // 这个是为了前端传过来可能会有转义字符变成空所以替换
        String s = encryptedData.replaceAll(" ", "+");
        byte[] dataByte = org.bouncycastle.util.encoders.Base64.decode(s);
        // 加密秘钥
        byte[] keyByte = org.bouncycastle.util.encoders.Base64.decode(session_key);
        // 偏移量
        byte[] ivByte = org.bouncycastle.util.encoders.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 JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值