Wechat applets log in to their own applications

Keywords: Front-end Session Database JSON Spring

My hobby is to make plans, overturn plans, make plans again, and let others supervise my study, supervise my weight loss, and supervise me to change my bad habits. So I'm going to make a little program for myself. The layout of the applet interface is almost finished. Now let's register and log in your application.

1, Applet side:

1,.wxml

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

2. . js: call the interface wx.login to get the code, wx.getUserInfo to get the encryptedData and iv, and pass the code, encryptedData and iv to the background

getUserInfo: function () {
    //Open the loading box
    wx.showLoading({
      title: 'Logging in...',
      mask: true
    });
    // Sign in
    wx.login({
      success: function (res_login) {
        if (res_login.code) {
          //Get user information
          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. Save user information to local storage
                  wx.setStorageSync('userInfo', res.data)
                  //2. Save user information to global variables
                  var app = getApp();
                  app.globalData.userInfo = res.data
                  //Hide loading box
                  wx.hideLoading();
                },
                fail: res => {
                  wx.showToast({
                    title: 'Login failed',
                    icon: 'none'
                  })
                }
              })
            }
          })
        } 
      }
    });
  },

2, Use Spring boot for backend

1. Get openid according to code

The backend receives the code from the applet, and sends it to the wechat server together with appid and secret to obtain the openid and session Φ u key. Openid is mainly used to register and log in, and the openid existence database is the unique identification of user existence. Session [u key is used as the state to judge whether to log off or not, and the returned business data will take this state (do not return session [u key directly here, you can generate a unique string for each session as a key, and then you can use session [u key and openid as values).

/**
 * Wechat applet login registration (if there is a value through openID, the login information will be returned directly, otherwise the user information will be inserted into the database)
 * @param code code Parameter to get the user's openId
 * @param encryptedData Encrypted data of complete user information including sensitive data
 * @param iv Initial vector of encryption algorithm
 * @return
 */
@GetMapping("/wx_login")
public ResponseBO<WxResponseVO> wxLogin(@RequestParam(required = false) String code,String encryptedData, String iv) {

    // Get openID and 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) {
        //Analyze the openid and session_key obtained from wechat server;
        String sesionData = sessionResponseEntity.getBody();
        Gson gson = new Gson();
        WxResponseVO weChatSession = gson.fromJson(sesionData, WxResponseVO.class);

        //Get session key
        String session_key = weChatSession.getSession_key();

        // Cache session [key
        RedisUtils.set("session_key", session_key, weChatSession.getExpires_in());

        //Get the unique identity of the user
        String openid = weChatSession.getOpenid();

        // Query the database according to openID. If there is a value, the login information will be returned directly. If there is no value, the user information will be inserted into the database
        String userInfo = getUserInfo(encryptedData,session_key,iv);
        
    }
   return null;
}

2. According to session_key, encryptedData and iv, wechat user information can be decrypted.

 /**
     * Decrypt user sensitive data to obtain user information
     * @param sessionkey Key to encrypt and sign data
     * @param encryptedData Encrypted data of complete user information including sensitive data
     * @param iv Initial vector of encryption algorithm
     */
    public String getUserInfo(String sessionkey, String encryptedData,  String iv){
        // Encrypted data
        byte[] dataByte = Base64.decode(encryptedData);
        // Encryption key
        byte[] keyByte = Base64.decode(sessionkey);
        // Offset
        byte[] ivByte = Base64.decode(iv);
        try {
            // If the key is less than 16 bits, it will be supplemented. The content in this if is very important
            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;
            }
            // initialization
            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);// initialization
            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;
    }

3, After logging in, it returns the session [u key] to the applet. The applet uses Wx. Setstoragesync ('session [u key], res.data. Data. Session [u key) to cache. Later, the returned business data will take this status.

Posted by Obsession on Sun, 10 May 2020 07:07:06 -0700