微信小程序登陆自己的应用程序

試著忘記壹切 提交于 2020-08-10 14:04:27

我的爱好就是做计划,推翻计划,重新做计划,还有就是让别人监督我学习,监督我减肥,监督我改掉坏习惯。所以我准备为自己量身定做个小程序。小程序界面差不多布局好了,现在来实现小程序注册登陆自己的应用程。

一、小程序端:

1、.wxml

<view class="container">
  <button class="to-login" open-type="getUserInfo" bindtap="getUserInfo">登陆</button>
</view>

2、.js:调用接口wx.login获取code,调用 wx.getUserInfo获取encryptedData和iv,将code,encryptedData和iv传到后台

getUserInfo: function () {
    //开启loading框
    wx.showLoading({
      title: '正在登录...',
      mask: true
    });
    // 登录
    wx.login({
      success: function (res_login) {
        if (res_login.code) {
          //获取用户信息
          wx.getUserInfo({
            lang:'zh_CN',
            success: res => {
              console.log(res)
              wx.request({
                url: 'http://192.168.1.101:8080/login/wx_login',
                data: {
                  code: res_login.code,
                  encryptedData: res.encryptedData,
                  iv: res.iv
                },
                header: {
                  'content-type': 'application/json'
                },
                success: res => {
                  //1.存用户信息到本地存储
                  wx.setStorageSync('userInfo', res.data)
                  //2.存用户信息到全局变量
                  var app = getApp();
                  app.globalData.userInfo = res.data
                  //隐藏loading框
                  wx.hideLoading();
                },
                fail: res => {
                  wx.showToast({
                    title: '登录失败',
                    icon: 'none'
                  })
                }
              })
            }
          })
        } 
      }
    });
  },

二、后端使用Spring boot

1、根据code获取openid

后端接收小程序传来的code,和appid,secret一起发送给微信服务器,获得openid和session_key。openid主要用于注册登陆,openid存在数据库作为用户存在的唯一标识。session_key用于作为判断是否断登陆的状态,后面返回业务数据都带这个状态(这里不要直接返回session_key,可以为每个session生成一个唯一的字符串作为键,然后可以将session_key和openid作为值)。

/**
 * 微信小程序登陆注册(通过openID有值则直接返回登陆信息,否则将用户信息插入到数据库)
 * @param code code参数获取用户的openId
 * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
 * @param iv 加密算法的初始向量
 * @return
 */
@GetMapping("/wx_login")
public ResponseBO<WxResponseVO> wxLogin(@RequestParam(required = false) String code,String encryptedData, String iv) {

    // 获取openID和session_key
    String SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=" + APPID +
            "&secret=" + SECRET + "&js_code=" + code + "&grant_type=authorization_code";

    RestTemplate sessionRestTemplate = new RestTemplate();
    ResponseEntity<String> sessionResponseEntity = sessionRestTemplate.exchange(SESSION_URL, HttpMethod.GET, null, String.class);
    if (sessionResponseEntity != null && sessionResponseEntity.getStatusCode() == HttpStatus.OK) {
        //解析从微信服务器获得的openid和session_key;
        String sesionData = sessionResponseEntity.getBody();
        Gson gson = new Gson();
        WxResponseVO weChatSession = gson.fromJson(sesionData, WxResponseVO.class);

        //获取会话秘钥
        String session_key = weChatSession.getSession_key();

        // 缓存session_key
        RedisUtils.set("session_key", session_key, weChatSession.getExpires_in());

        //获取用户的唯一标识
        String openid = weChatSession.getOpenid();

        // 根据openID查询数据库,有值则直接返回登陆信息,没有值则将用户信息插入到数据库
        String userInfo = getUserInfo(encryptedData,session_key,iv);
        
    }
   return null;
}

2、根据session_key,encryptedData和iv可解密出微信用户信息。

 /**
     * 解密用户敏感数据获取用户信息
     * @param sessionkey 数据进行加密签名的密钥
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param iv 加密算法的初始向量
     */
    public String getUserInfo(String sessionkey, String encryptedData,  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 result;
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
        return null;
    }

三、登陆后返回session_key到小程序端,小程序端 使用wx.setStorageSync('session_key', res.data.data.session_key)缓存,后面返回业务数据都带这个状态。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!