ソースを参照

扫码登录优化

chao 4 年 前
コミット
36b4428b28

+ 24 - 8
src/main/java/com/caimei365/user/components/WeChatService.java

@@ -89,6 +89,12 @@ public class WeChatService {
         return crmAppSecret;
     }
 
+    public static class Keys {
+        public static final String OPEN_ID = "openid";
+        public static final String UNION_ID = "unionid";
+        public static final String SESSION_KEY = "session_key";
+    }
+
     static {
         // BouncyCastle是一个开源的加解密解决方案
         Security.addProvider(new BouncyCastleProvider());
@@ -161,15 +167,15 @@ public class WeChatService {
         }
         // 解析相应内容(转换成json对象)
         JSONObject jsonObject = JSON.parseObject(infos);
-        String openId = jsonObject.getString("openid");
-        String unionId = jsonObject.getString("unionid");
-        String sessionKey = jsonObject.getString("session_key");
+        String openId = jsonObject.getString(Keys.OPEN_ID);
+        String unionId = jsonObject.getString(Keys.UNION_ID);
+        String sessionKey = jsonObject.getString(Keys.SESSION_KEY);
         String errCode = jsonObject.getString("errcode");
         String errMsg = jsonObject.getString("errmsg");
         log.info("openId----->" + openId +", unionId------>" + unionId);
-        returnMap.put("openid", openId);
-        returnMap.put("unionid", unionId);
-        returnMap.put("session_key", sessionKey);
+        returnMap.put(Keys.OPEN_ID, openId);
+        returnMap.put(Keys.UNION_ID, unionId);
+        returnMap.put(Keys.SESSION_KEY, sessionKey);
         boolean errFlag = StringUtils.isNotEmpty(errCode) && ("-1".equals(errCode) || "40029".equals(errCode) || "45011".equals(errCode));
         if (errFlag) {
             return ResponseJson.error(-1, errMsg, returnMap);
@@ -241,12 +247,22 @@ public class WeChatService {
      * 微信公众号获取用户信息
      * @return
      */
-    public Map<String, Object> getUserInfo(String accessToken, String openid) throws Exception {
-        String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
+    public Map<String, Object> getUserInfo(String accessToken, String openId) throws Exception {
+        String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
         String userInfo = RequestUtil.sendGet(requestUrl);
         log.info("微信公众号授权用户数据>>>>>>>>>>>" + userInfo);
         Map<String, Object> map = JSONObject.parseObject(userInfo, Map.class);
         return map;
     }
 
+    /**
+     * 网页授权登录,获取用户信息(UnionID机制)
+     */
+    public Map<String, Object> getUserInfoByWeb(String access_token, String openId) throws Exception {
+        String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openId;
+        String userInfo = RequestUtil.sendGet(requestUrl);
+        Map<String, Object> map = JSONObject.parseObject(userInfo, Map.class);
+        return map;
+    }
+
 }

+ 96 - 0
src/main/java/com/caimei365/user/config/TokenAspect.java

@@ -0,0 +1,96 @@
+//package com.caimei365.user.config;
+//
+//import com.caimei365.user.components.RedisService;
+//import com.caimei365.user.utils.JwtUtil;
+//import org.aspectj.lang.JoinPoint;
+//import org.aspectj.lang.annotation.Aspect;
+//import org.aspectj.lang.annotation.Before;
+//import org.aspectj.lang.annotation.Pointcut;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.context.request.RequestContextHolder;
+//import org.springframework.web.context.request.ServletRequestAttributes;
+//import org.springframework.web.server.ServerWebExchange;
+//
+//
+///**
+// * 把切面类加入到IOC容器中
+// * 所有请求都会更新redis存token的时间
+// *
+// * @author : Charles
+// * @date : 2020/3/17
+// */
+//@Component
+//@Aspect
+//public class TokenAspect {
+//
+//    private RedisService redisService;
+//    @Autowired
+//    public void setRedisService(RedisService redisService) {
+//        this.redisService = redisService;
+//    }
+//
+//    /**
+//     * 定义一个切入点 我这里是从controller切入
+//     */
+//    @Pointcut("execution(public * com.caimei365.user.controller..*.*(..))")
+//    public void pointCut() {
+//    }
+//
+//    /**
+//     * 前置通知
+//     * 在进入方法前执行 可以对参数进行限制或者拦截
+//     * 通常在这边做日志存储存到数据库中
+//     * @param joinPoint
+//     * @throws Throwable
+//     */
+//    @Before("pointCut()")
+//    public void before(JoinPoint joinPoint) throws Throwable {
+//
+//
+//        ServerWebExchange
+//
+//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+//
+//        String token = request.getHeader("X-Token");
+//        String cacheToken = null!=token ? String.valueOf(redisService.get(token)) : null;
+//        // Redis过期后会得到"null"值,所以需判断字符串"null"
+//        if (cacheToken != null && cacheToken.length() != 0 && !"null".equals(cacheToken)) {
+//            if (JwtUtil.isVerify(cacheToken)) {
+//               /* String mobileOrEmail = JwtUtil.parseTokenAud(cacheToken);*/
+//                int userId = JwtUtil.parseTokenUid(cacheToken);
+//                // 刷新token
+//                tokenRefresh(token, userId);
+//            }
+//        }
+//    }
+//
+//    /**
+//     * JWT Token续签:
+//     * 业务逻辑:登录成功后,用户在未过期时间内继续操作,续签token。
+//     * 登录成功后,空闲超过过期时间,返回token已失效,重新登录。
+//     * 实现逻辑:
+//     * 1.登录成功后将token存储到redis里面(这时候k、v值一样都为token),并设置过期时间为token过期时间
+//     * 2.当用户请求时token值还未过期,则重新设置redis里token的过期时间。
+//     * 3.当用户请求时token值已过期,但redis中还在,则JWT重新生成token并覆盖v值(这时候k、v值不一样了),然后设置redis过期时间。
+//     * 4.当用户请求时token值已过期,并且redis中也不存在,则用户空闲超时,返回token已失效,重新登录。
+//     */
+//    public boolean tokenRefresh(String token, Integer userID) {
+//        String cacheToken = String.valueOf(redisService.get(token));
+//        // 过期后会得到"null"值,所以需判断字符串"null"
+//        if (cacheToken != null && cacheToken.length() != 0 && !"null".equals(cacheToken)) {
+//            // 校验token有效性
+//            if (!JwtUtil.isVerify(cacheToken)) {
+//                // 生成token
+//                String newToken = JwtUtil.createToken(userID);
+//                // 将token存入redis,并设置超时时间
+//                redisService.set(token, newToken, JwtUtil.getExpireTime());
+//            } else {
+//                // 重新设置超时时间
+//                redisService.set(token, cacheToken, JwtUtil.getExpireTime());
+//            }
+//            return true;
+//        }
+//        return false;
+//    }
+//}

+ 18 - 17
src/main/java/com/caimei365/user/service/impl/LoginServiceImpl.java

@@ -116,17 +116,18 @@ public class LoginServiceImpl implements LoginService {
             return ResponseJson.error(appletsInfo.getMsg(), null);
         }
         Map<String, Object> infoData = appletsInfo.getData();
-        String openId = (String) infoData.get("openid");
-        String unionId = (String) infoData.get("unionid");
-        String sessionKey = (String) infoData.get("session_key");
+        String openId = (String) infoData.get(WeChatService.Keys.OPEN_ID);
+        String unionId = (String) infoData.get(WeChatService.Keys.UNION_ID);
+        String sessionKey = (String) infoData.get(WeChatService.Keys.SESSION_KEY);
+
         try {
             if (StringUtils.isEmpty(unionId) || StringUtils.isBlank(unionId)) {
                 String result = WeChatService.decrypt(encryptedData, sessionKey, iv, "UTF-8");
                 log.info("解密数据>>>>>>" + result);
                 Map parseMap = JSONObject.parseObject(result, Map.class);
                 assert parseMap != null;
-                unionId = parseMap.get("unionid").toString();
-                infoData.put("unionid", unionId);
+                unionId = parseMap.get(WeChatService.Keys.UNION_ID).toString();
+                infoData.put(WeChatService.Keys.UNION_ID, unionId);
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -185,7 +186,7 @@ public class LoginServiceImpl implements LoginService {
             try {
                 // 通过code获取微信用户信息
                 Map<String, Object> map = weChatService.getInfoMapByWeb(code, "crm");
-                String openId = (String) map.get("openid");
+                String openId = (String) map.get(WeChatService.Keys.OPEN_ID);
                 if (mode == 1) {
                     // 静默授权
                     Integer userId = loginMapper.getUserIdByOpenId(openId, "www");
@@ -201,7 +202,7 @@ public class LoginServiceImpl implements LoginService {
                     String accessToken = weChatService.getAccessToken();
                     // 获取微信用户信息
                     Map<String, Object> infoData = weChatService.getUserInfo(accessToken, openId);
-                    String unionId = (String) infoData.get("unionid");
+                    String unionId = (String) infoData.get(WeChatService.Keys.UNION_ID);
                     // 用户数据存入Redis,key前缀:wxInfo:website:
                     redisService.setMap("wxInfo:website:" + unionId, infoData);
                     log.info("移动端授权登录,返回unionId给前端,用户数据存入Redis,key:wxInfo:website:" + unionId);
@@ -314,11 +315,11 @@ public class LoginServiceImpl implements LoginService {
             // 用code换取access_token
             Map<String, Object> tokenMap = weChatService.getInfoMapByWeb(code, "pc");
             String accessToken = (String) tokenMap.get("access_token");
-            String openid = (String) tokenMap.get("openid");
-            log.info(">>>>>wx回调openId:" + openid + " ,accessToken"+ accessToken);
+            String openId = (String) tokenMap.get(WeChatService.Keys.OPEN_ID);
+            log.info(">>>>>(code换取access_token)wx回调openId:" + openId + " ,accessToken:"+ accessToken);
             // 用access_token获取微信用户信息
-            Map<String, Object> infoData = weChatService.getUserInfo(accessToken, openid);
-            log.info(">>>>>wx回调openId:" + infoData.get("openid") + " ,unionId"+ infoData.get("unionid"));
+            Map<String, Object> infoData = weChatService.getUserInfoByWeb(accessToken, openId);
+            log.info(">>>>>(用access_token获取用户信息)wx回调openId:" + infoData.get(WeChatService.Keys.OPEN_ID) + " ,unionId:"+ infoData.get(WeChatService.Keys.UNION_ID));
             // 微信用户信息存入redis
             redisService.setMap("scan:" + state, infoData);
         } catch (Exception e) {
@@ -349,9 +350,9 @@ public class LoginServiceImpl implements LoginService {
         }
         // 清除redis的扫码数据
         redisService.remove("scan:" + state);
-        String unionId = (String) infoData.get("unionid");
-        String openId = (String) infoData.get("openid");
-        log.info(">>>>>>pc商城unionId:" + unionId + " ,openid:" + openId);
+        String unionId = (String) infoData.get(WeChatService.Keys.UNION_ID);
+        String openId = (String) infoData.get(WeChatService.Keys.OPEN_ID);
+        log.info(">>>>>>pc商城unionId:" + unionId + " ,openId:" + openId);
         // 用户数据存入Redis,key前缀:wxInfo:website:
         String infoDataStr = JSON.toJSONString(infoData);
         Map<String, Object> infoDataMap = JSON.parseObject(infoDataStr);
@@ -391,7 +392,7 @@ public class LoginServiceImpl implements LoginService {
             }
             Map<Object, Object> infoData = redisService.getEntries("wxInfo:website:" + unionId);
             log.info("扫码绑定微信, 获取unionId>>>>>>" + unionId);
-            String openId = (String) infoData.get("openid");
+            String openId = (String) infoData.get(WeChatService.Keys.OPEN_ID);
             String nickName = (String) infoData.get("nickname");
             String avatarUrl = (String) infoData.get("headimgurl");
             // 判断微信是否已经绑定
@@ -490,7 +491,7 @@ public class LoginServiceImpl implements LoginService {
         operationPo.setUnionId(unionId);
         Map<Object, Object> infoData = redisService.getEntries("wxInfo:applets:" + unionId);
         // 微信openId
-        operationPo.setOpenId((String) infoData.get("openid"));
+        operationPo.setOpenId((String) infoData.get(WeChatService.Keys.OPEN_ID));
         // 微信昵称
         operationPo.setNickName(nickName);
         // 微信头像
@@ -547,7 +548,7 @@ public class LoginServiceImpl implements LoginService {
         }
         Map<Object, Object> infoData = redisService.getEntries("wxInfo:applets:" + unionId);
         log.info("绑定微信bindingWx,获取unionId>>>>>>" + unionId);
-        String openId = (String) infoData.get("openid");
+        String openId = (String) infoData.get(WeChatService.Keys.OPEN_ID);
         // 判断微信是否已经绑定
         UserLoginVo operationByUnionId = loginMapper.getLoginUserByUnionId(unionId,"mini");
         if (operationByUnionId != null) {

+ 2 - 1
src/main/java/com/caimei365/user/service/impl/RegisterServiceImpl.java

@@ -1,6 +1,7 @@
 package com.caimei365.user.service.impl;
 
 import com.caimei365.user.components.CommonService;
+import com.caimei365.user.components.WeChatService;
 import com.caimei365.user.mapper.BaseMapper;
 import com.caimei365.user.mapper.LoginMapper;
 import com.caimei365.user.mapper.RegisterMapper;
@@ -213,7 +214,7 @@ public class RegisterServiceImpl implements RegisterService{
             // 微信unionId
             operation.setUnionId(clubRegisterDto.getUnionId());
             Map<Object, Object> infoData = redisService.getEntries("wxInfo:applets:" + clubRegisterDto.getUnionId());
-            String openId = (String) infoData.get("openid");
+            String openId = (String) infoData.get(WeChatService.Keys.OPEN_ID);
             // 微信openId
             operation.setOpenId(openId);
             // 添加时间

+ 5 - 1
src/main/java/com/caimei365/user/service/impl/SellerServiceImpl.java

@@ -1,6 +1,7 @@
 package com.caimei365.user.service.impl;
 
 import com.caimei365.user.components.RedisService;
+import com.caimei365.user.components.WeChatService;
 import com.caimei365.user.mapper.SellerMapper;
 import com.caimei365.user.model.ResponseJson;
 import com.caimei365.user.model.vo.UserLoginVo;
@@ -27,8 +28,11 @@ public class SellerServiceImpl implements SellerService {
     @Resource
     private RedisService redisService;
     @Resource
+    private WeChatService weChatService;
+    @Resource
     private SellerMapper sellerMapper;
 
+
     /**
      * 协销登录(手机号,密码)
      *
@@ -52,7 +56,7 @@ public class SellerServiceImpl implements SellerService {
         String token = JwtUtil.createToken(seller.getUserId());
         seller.setToken(token);
         Map<Object, Object> infoData = redisService.getEntries("wxInfo:applets:" + unionId);
-        String openId = (String) infoData.get("openid");
+        String openId = (String) infoData.get(WeChatService.Keys.OPEN_ID);
         sellerMapper.updateServiceProviderByUserId(seller.getUserId(), openId, unionId);
         log.info("协销账号密码登录openid>>>>" + openId + " ,unionId>>>>>" + unionId);
         return ResponseJson.success(seller);