小程序开发(1)——授权登录

小程序开发(1)——授权登录

最近公司在做小程序项目,第一次接触小程序开发,踩了很多坑,整理了一些常见问题,分享给大家。今天先总结一下微信小程序单点登录:

微信官方登陆流程图:

我的登录流程:

小程序登录主要流程

1小程序发起登陆请求,调用wx.login()获取临时登陆凭证code。请求至后台。
2 通过code调用微信接口换取用户唯一标识openid和会话秘钥session_key
3 自己生成一个唯一标识3rd_session作为key,使用openid和session_key组合加密作为value保存至缓存(可以使用redis作为缓存)。
4.根据业务需求处理微信用户信息。
5 后台返回给小程序端key值,作为登录状态(可以保存至微信缓存,也可以定义成全局变量)。
6.后续请求如果需要openid,小程序端获取key,,请求至后台在后台缓存中获取openid。

小程序端主要代码

 1bindGetUserInfo: function bindGetUserInfo(e) {
 2    var that = this;
 3    if (e.detail.userInfo) {
 4      wx.login({
 5        success: function success(loginRes) {
 6          if (loginRes) {
 7            //获取用户信息
 8            wx.getUserInfo({
 9              withCredentials: true, //非必填  默认为true
10              success: function success(infoRes) {
11                //请求服务端的登录接口
12                wx.request({
13                  url: app.globalData.url + "LoginController",
14                  data: {
15                    code: loginRes.code, //临时登录凭证
16                    rawData: infoRes.rawData, //用户非敏感信息
17                    signature: infoRes.signature, //签名
18                    encrypteData: infoRes.encryptedData, //用户敏感信息
19                    iv: infoRes.iv //解密算法的向量
20                  },
21                  success: function success(res) {
22                    console.log("login success"); 
24                    app.globalData.sessionid = res.data.sessionId;
26                    wx.setStorageSync("sessionid", res.data.sessionId);
27                    that.util("close");
28                  }
29                });
30              }
31            });
32          }
33        }
34      });
35
36      //授权成功后,跳转进入小程序首页
37    } else {
38      //用户按了拒绝按钮
39      wx.showModal({
40        title: "提示",
41        content: "拒绝授权,将无法提供部分服务哦!",
42        showCancel: false,
43        success: function success(res) {
44          that.util("close");
45        }
46      });
47    }
48  }

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

扫描二维码关注公众号,回复: 4239881 查看本文章

Java后端主要代码

1 控制层

 1String iv = request.getParameter("iv");
 2        String encrypteData = request.getParameter("encrypteData");
 3        String APPID = Utility.getSysParameter("WeChatAppID");
 4        String SECRET = Utility.getSysParameter("appSecret");
 5
 6        String grant_type = "authorization_code";
 7        // 微信官方获取openid接口
 8        String WX_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
 9        String requestUrl = WX_URL.replace("APPID", APPID)
10                .replace("SECRET", SECRET).replace("JSCODE", code)
11                .replace("authorization_code", grant_type);
12        String returnvalue =WxUtils.getDataByUrl(code);
13        JSONObject jo = JSONObject.fromObject(returnvalue);
14        String openid = (String) jo.get("openid");
15        String session_key = (String) jo.get("session_key");
16        //解密用户信息
17        byte[] bytes = null;
18        try {
19            bytes = decrypt(Base64.decodeBase64(session_key.getBytes()),
20                    Base64.decodeBase64(iv.getBytes()),
21                    Base64.decodeBase64(encrypteData.getBytes()));
22        } catch (Exception e) {
23            e.printStackTrace();
24        }
25        String userinfo = new String(bytes, "UTF8");    
26        //保存用户信息
27        JSONObject jsonObject = JSONObject.fromObject(userinfo);
28        insertUser(jsonObject, openid);
29        try {
30            Registeredusers(jsonObject,openid);
31        } catch (Exception e) {
32            e.printStackTrace();
33        }
34        Jedis  jedis = redisUtil.getJedis();  
35        //清除以前缓存
36        if (jedis.hexists("TODELETE",openid)) {
37            String oldSesssionId = jedis.hget("TODELETE",openid);
38            jedis.hdel("TODELETE",openid);
39            if(jedis.hexists("SessionAndOpenId",oldSesssionId)){
40                jedis.hdel("SessionAndOpenId",oldSesssionId);
41            }
42        }
43        //redis缓存openid以及sessionkey
44        String sessionId = UUID.randomUUID().toString().replaceAll("-", "");
45        jedis.hset("TODELETE", openid, sessionId);
46        jedis.hset("SessionAndOpenId", sessionId, openid+sessionId+session_key);
47        JSONObject jsonObject2 = new JSONObject();
48        jsonObject2 .put("sessionId", sessionId);
49        //将用户信息返回至小程序端

使用redis维护sessionid

维护3rd_session需要一个内存数据库,这里我选用了redis
维护会话态是内存数据库的典型应用场景,毕竟量小,并且要求速度快,这么一个小应用,当然也可以自己在内存中维护一个对象来进行会话id的处理,但是肯定难以跟一个成熟的系统相媲美
抛开代码实现,这似乎就是一句话可以概括的事情,生成一个唯一的随机串sessionid,以此为key,openid和微信方的session_key为value存入redis,并把sessionid传回给客户端。

2工具类

 1/**
 2     * <p>Title: getDataByUrl</p>  
 3     * <p>Description:使用微信开放接口获取openid和sessionkey </p>  
 4     * @param url
 5     * @return
 6     */
 7    public static String getDataByUrl(String url) {
 8        String result = "";
 9        BufferedReader in = null;
10        InputStream is = null;
11        InputStreamReader isr = null;
12        try {
13            URL realUrl = new URL(url);
14            URLConnection conn = realUrl.openConnection();
15            conn.connect();
16            is = conn.getInputStream();
17            isr = new InputStreamReader(is);
18            in = new BufferedReader(isr);
19            String line;
20            while ((line = in.readLine()) != null) {
21                result += line;
22            }
23        } catch (Exception e) {
24            e.printStackTrace();
25        } finally {
26            try {
27                if (in != null)in.close();
28                if (is != null)is.close();
29                if (isr != null)isr.close();
30            } catch (Exception ex) {
31                ex.printStackTrace();
32            }
33        }
34        return result;
35    }
36    /**
37     * <p>Title: decrypt</p>  
38     * <p>Description: 解密微信用户敏感信息 </p>  
39     * @param sessionkey
40     * @param iv
41     * @param encryptedData
42     * @return
43     * @throws Exception
44     */
45    public static byte[] decrypt(byte[] sessionkey, byte[] iv,byte[] encryptedData) throws Exception {
46        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
47        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
48        SecretKeySpec keySpec = new SecretKeySpec(sessionkey, "AES");
49        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
50        return cipher.doFinal(encryptedData);
51    }

一结语

小程序登录相对灵活,可根据自己实际业务需求,进行代码设计。

                                            扫一扫,关注Java开发之美,获取更多视频书籍资料

                                                                   

猜你喜欢

转载自blog.csdn.net/qq_20807967/article/details/84502789