Selaa lähdekoodia

app扫码登录功能

Qchen 2 vuotta sitten
vanhempi
commit
10f3a4efe1

+ 3 - 0
src/main/java/com/ydtech/components/TokenInterceptor.java

@@ -19,6 +19,9 @@ public class TokenInterceptor {
         notMatchList.add("/api/demo/**"); // 演示接口
         notMatchList.add("/captcha.jpg**"); // 验证码
         notMatchList.add("/login");
+        notMatchList.add("/getQrCode");  //获取登录二维码
+        notMatchList.add("/scanQrCode");  //扫描登录二维码
+        notMatchList.add("/getQrCodeStatus");  //获取登录二维码状态
 
         notMatchList.add("/wechat/login");  // 微信登陆
 

+ 107 - 0
src/main/java/com/ydtech/modules/admin/controller/SysLoginController.java

@@ -3,6 +3,8 @@ package com.ydtech.modules.admin.controller;
 import cn.dev33.satoken.session.SaSession;
 import cn.dev33.satoken.stp.StpUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.code.kaptcha.Producer;
 import com.ydtech.config.MasterPasswordConfig;
 import com.ydtech.core.page.HttpResult;
@@ -10,7 +12,11 @@ import com.ydtech.exception.SystemException;
 import com.ydtech.modules.admin.model.SysRole;
 import com.ydtech.modules.admin.model.SysUser;
 import com.ydtech.modules.admin.model.vo.LoginBean;
+import com.ydtech.modules.admin.model.vo.LoginTicket;
 import com.ydtech.modules.admin.model.vo.PhoneLoginVo;
+import com.ydtech.modules.admin.model.vo.QrCodeStatusEnum;
+import com.ydtech.modules.base.controller.BaseController;
+import com.ydtech.utils.RedisUtils;
 import com.ydtech.modules.admin.service.SysUserRoleService;
 import com.ydtech.modules.admin.service.SysUserService;
 import com.ydtech.security.utils.PasswordUtils;
@@ -362,5 +368,106 @@ public class SysLoginController {
         return HttpResult.ok("退出登录成功");
     }
 
+    /**
+     * 获取二维码生成的uuid
+     */
+    @GetMapping("/getQrCode")
+    public HttpResult getQrCode(@RequestParam String uuid) throws JsonProcessingException {
+//        String uuid = UUID.randomUUID().toString();
+        int statusCode = QrCodeStatusEnum.WAITING.getStatusCode();
+        LoginTicket loginTicket = new LoginTicket();
+        // 二维码最初为 waitting 状态
+        loginTicket.setStatusCode(statusCode);
+        loginTicket.setUuid(uuid);
+        ObjectMapper objectMapper = new ObjectMapper();
+        String jsonContent = objectMapper.writeValueAsString(loginTicket);
+        redisTemplate.opsForValue().set(uuid, jsonContent);
+        //设置过期时间60秒
+        redisTemplate.expire(uuid, 60, TimeUnit.SECONDS);
+
+        Map<String, Object> resultMap = new HashMap<>();
+        resultMap.put("uuid", uuid);
+        resultMap.put("statusCode", QrCodeStatusEnum.WAITING.getStatusValue());
+        return HttpResult.ok(resultMap);
+    }
+
+    /**
+     * 扫描二维码 改变redis中相关uuid状态并于对应用户关联
+     */
+    @PostMapping("/scanQrCode")
+    public HttpResult scanQrCode(@RequestParam String uuid) {
+        Map<String, Object> data = new HashMap<>();
+        try {
+            ObjectMapper objectMapper = new ObjectMapper();
+            String content = redisTemplate.opsForValue().get(uuid);
+            LoginTicket loginTicket = objectMapper.readValue(content, LoginTicket.class);
+
+            // redis 中 uuid的过期时间
+            Long expired = RedisUtils.timeToLive(uuid);
+            boolean valid = loginTicket != null &&
+                    QrCodeStatusEnum.WAITING.getStatusCode().equals(loginTicket.getStatusCode()) &&
+                    expired != null &&
+                    expired >= 0;
+            if (valid) {
+                String user = BaseController.getUser().getId();
+                if (user == null) {
+                    throw new RuntimeException("用户未登录");
+                }
+                // 修改扫码状态
+                loginTicket.setStatusCode(QrCodeStatusEnum.SCANNED.getStatusCode());
+                // 将二维码与用户进行关联
+                loginTicket.setUserId(user);
+                String jsonContent = objectMapper.writeValueAsString(loginTicket);
+                redisTemplate.opsForValue().set(uuid, jsonContent);
+                data.put("statusCode", QrCodeStatusEnum.SCANNED.getStatusCode());
+                return HttpResult.ok(data);
+            } else {
+                data.put("statusCode", QrCodeStatusEnum.INVALID);
+                return HttpResult.error("二维码已过期");
+            }
+        } catch (RuntimeException | JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     *  轮询接口 获取二维码状态
+     */
+    @PostMapping("/getQrCodeStatus")
+    public HttpResult getQrCodeStatus(HttpServletRequest request, HttpServletResponse response,
+        @RequestParam String uuid) throws JsonProcessingException {
+
+        Map<Object, Object> resultMap = new HashMap<>();
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        String content = redisTemplate.opsForValue().get(uuid);
+        LoginTicket loginTicket = objectMapper.readValue(content, LoginTicket.class);
 
+        if (loginTicket == null) {
+            resultMap.put("statusCode", QrCodeStatusEnum.INVALID);
+            resultMap.put("status", QrCodeStatusEnum.INVALID.getStatusValue());
+            return HttpResult.ok(resultMap);
+        }
+        Integer statusCode = loginTicket.getStatusCode();
+        //二维码状态为待扫描
+        if (statusCode.equals(QrCodeStatusEnum.WAITING.getStatusCode())) {
+            resultMap.put("statusCode", statusCode);
+            resultMap.put("status", QrCodeStatusEnum.WAITING.getStatusValue());
+        }
+        //二维码状态为无效时删除redis中所存的uuid
+        if (statusCode.equals(QrCodeStatusEnum.INVALID.getStatusCode())) {
+            resultMap.put("statusCode", statusCode);
+            resultMap.put("status", QrCodeStatusEnum.INVALID.getStatusValue());
+            RedisUtils.del(uuid);
+        }
+        //二维码状态为以扫描
+        SysUser user = sysUserService.getById(loginTicket.getUserId());
+        if (statusCode.equals(QrCodeStatusEnum.SCANNED.getStatusCode())) {
+            String token = StpUtil.createLoginSession(user.getId());
+            resultMap.put("token", token);
+            resultMap.put("statusCode", statusCode);
+            resultMap.put("status", QrCodeStatusEnum.SCANNED.getStatusValue());
+        }
+        return HttpResult.ok(resultMap);
+    }
 }

+ 11 - 0
src/main/java/com/ydtech/modules/admin/model/vo/LoginTicket.java

@@ -0,0 +1,11 @@
+package com.ydtech.modules.admin.model.vo;
+
+import lombok.Data;
+
+@Data
+public class LoginTicket {
+    private String userId;
+    private String uuid;
+    private Integer statusCode;
+
+}

+ 24 - 0
src/main/java/com/ydtech/modules/admin/model/vo/QrCodeStatusEnum.java

@@ -0,0 +1,24 @@
+package com.ydtech.modules.admin.model.vo;
+
+
+public enum QrCodeStatusEnum {
+    WAITING(10000,"待扫描"),
+    SCANNED(20000,"已扫描"),
+    INVALID(30000,"二维码无效");
+
+    private Integer statusCode;
+    private String statusValue;
+
+    QrCodeStatusEnum(Integer statusCode, String statusValue) {
+        this.statusCode = statusCode;
+        this.statusValue = statusValue;
+    }
+
+    public Integer getStatusCode() {
+        return statusCode;
+    }
+
+    public String getStatusValue() {
+        return statusValue;
+    }
+}