From 65c41326f4e7064890120dee7c480e95315c993d Mon Sep 17 00:00:00 2001 From: Ziin Date: Tue, 5 Aug 2025 21:15:01 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=B7=BB=E5=8A=A0=20web=20=E7=AB=AF=E6=89=AB?= =?UTF-8?q?=E7=A0=81=E7=99=BB=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.cache/.Apifox_Helper/.toolWindow.db | Bin 180224 -> 188416 bytes pom.xml | 12 ++- .../java/vvpkassistant/Tools/QRCodeUtil.java | 31 ++++++ .../User/controller/UserController.java | 40 +++++++- .../User/model/DTO/LoginInfoDTO.java | 29 ++++++ .../User/model/DTO/ScanInfoDTO.java | 13 +++ .../User/model/QrcodeEntity.java | 13 +++ .../vvpkassistant/User/model/QrcodeVO.java | 15 +++ .../vvpkassistant/User/model/ResponseVO.java | 32 ++++++ .../vvpkassistant/User/model/UserModelVO.java | 1 + .../model/enumeration/LoginStatusEnum.java | 17 ++++ .../User/service/UserService.java | 9 ++ .../User/service/UserServiceImpl.java | 92 +++++++++++++++++- .../java/vvpkassistant/common/ErrorCode.java | 1 + .../config/SaTokenConfigure.java | 9 +- target/classes/application.yml | 7 +- 16 files changed, 311 insertions(+), 10 deletions(-) create mode 100644 src/main/java/vvpkassistant/Tools/QRCodeUtil.java create mode 100644 src/main/java/vvpkassistant/User/model/DTO/LoginInfoDTO.java create mode 100644 src/main/java/vvpkassistant/User/model/DTO/ScanInfoDTO.java create mode 100644 src/main/java/vvpkassistant/User/model/QrcodeEntity.java create mode 100644 src/main/java/vvpkassistant/User/model/QrcodeVO.java create mode 100644 src/main/java/vvpkassistant/User/model/ResponseVO.java create mode 100644 src/main/java/vvpkassistant/User/model/enumeration/LoginStatusEnum.java diff --git a/.idea/.cache/.Apifox_Helper/.toolWindow.db b/.idea/.cache/.Apifox_Helper/.toolWindow.db index 2d8ba4bbd809b1f09042ee46b47d553e29d81736..b7b7bfdeca60b9f5f9229698e96f004f17889a36 100644 GIT binary patch delta 6062 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 N3;2QHmmkF={|#9RQI!Ay delta 1204 zcmaiyYfKzf6vyY>-3wc{r9AdI`TR*p#3qv`~_!yF0TLQ*AX= z5-ky8Yy$d$%_N-|YoOM~`ixrww*}LdrfRg3G-)7wsV!it4aGhZ)JTh7Hhyn1=a)Ob z|C!9py{G?@vA^Fq?7-y=!&tJOCMeJC|Aey{xOpm=t=t;-C-;E6%l*bJayPj7T=skY z*dqUcef#w`p(R0EOfibG5JhP{MF~$)?542TD9ptaMTVy+6PDu)w`MtRJ7K?KU2<6+ zKiLJ_i%!W=Vw-mEbDm-E+S|D~SJHLOe#ddo{-*nHtIuwqKIaVkLoWM#S#ER^sW;kroZxk>pkAx=K#S_#%|o-gi?T_5Z8wkO8=3a_Tkybk zb&Bdn^%m8!ysrNWd7we{?cqUE+bE-I&mJB}@?rA=eI~44pdyqPS68SAs)i08M76eq z$AP@wyhgQO?WI~!Pf*sY(=@Ehhi!%Q4YjJVlZP5r=;ZOXyq+;35BBAkBX-(Rt&Y&F zDlZPlkw-nb*XPM31L3qJN77Mxr8DW26bQ>wC?X`2fpkcc#+LWm@hSai|NqrY^q1gw z4n5PZ{c#g4d|}BxhMhCdn$DDcR{CAZJ$hS8&#;8n#)(>J73H#%8?$h9vu>a$p}jW& z!_cBR3Cu#X_K?65G--3^U>)LQ_B_-8Y$s?6*7dp}ZzDN1ioAGYKhk?X)i)y#Yh)6P z!)9JFohutJ{c+2@;j%7+{7}avvRPg?&|R=quom`+mQ(5VhH(gbWo`@x4!FWJy7PgAEPVLyYX8L z^Q1k~%44Wg8;BuRJK2S*wW~4oB_}I%Z&N8z@Q0&GA(WERVp8!Z6;YJaf~;sSoCou! z9nZcj?>HFf?9hg*kX1^id%E99_9(9?Jue-S->P`^kgPl>S2R>S@e2l8QQRX36-CIT zQc5b4$;iQs97#sxV1!ah%Tgeq`9*ZlBd4WgP)R8fMG>Ql5EdhTDH>41QczR`IS|nx zjuy1DK4jL`*S0a;kGl+iC{%t}9Tj2=f0P||`9piGrhj1j9O@eOd=@99?4V4&z zjsYs=DC%R_F|%5nHF|N1>C0xj zb%UuGnK_Mq)k6b0`#HLTK_b21pl%FNvM`PSLxe0%A{W*T?Fhutool-all 5.8.38 - com.sun.mail javax.mail 1.6.2 + + + com.google.zxing + core + 3.4.1 + + + com.google.zxing + javase + 3.4.1 + diff --git a/src/main/java/vvpkassistant/Tools/QRCodeUtil.java b/src/main/java/vvpkassistant/Tools/QRCodeUtil.java new file mode 100644 index 0000000..ff0bef8 --- /dev/null +++ b/src/main/java/vvpkassistant/Tools/QRCodeUtil.java @@ -0,0 +1,31 @@ +package vvpkassistant.Tools; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.client.j2se.MatrixToImageWriter; +import com.google.zxing.common.BitMatrix; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Base64; +import java.util.Hashtable; + +public class QRCodeUtil { + + public static String generateQRCode(String content, int width, int height) + throws WriterException, IOException { + + Hashtable hints = new Hashtable<>(); + hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); + + BitMatrix matrix = new MultiFormatWriter().encode( + content, BarcodeFormat.QR_CODE, width, height, hints); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + MatrixToImageWriter.writeToStream(matrix, "PNG", outputStream); + + return Base64.getEncoder().encodeToString(outputStream.toByteArray()); + } +} \ No newline at end of file diff --git a/src/main/java/vvpkassistant/User/controller/UserController.java b/src/main/java/vvpkassistant/User/controller/UserController.java index a8e8992..20cdeb3 100644 --- a/src/main/java/vvpkassistant/User/controller/UserController.java +++ b/src/main/java/vvpkassistant/User/controller/UserController.java @@ -9,9 +9,12 @@ import vvpkassistant.Data.ResponseData; import vvpkassistant.Data.ResponseInfo; import vvpkassistant.Data.WxChatParam; import vvpkassistant.User.mapper.UserDao; +import vvpkassistant.User.model.DTO.LoginInfoDTO; +import vvpkassistant.User.model.DTO.ScanInfoDTO; import vvpkassistant.User.model.DTO.UserModelDTO; import vvpkassistant.User.model.UserModel; import vvpkassistant.User.model.UserModelVO; +import vvpkassistant.User.model.enumeration.LoginStatusEnum; import vvpkassistant.User.service.UserService; import vvpkassistant.common.ErrorCode; import vvpkassistant.config.FunctionConfigHolder; @@ -123,7 +126,10 @@ public class UserController { // return ResponseData.error(ResponseInfo.ERROR,"创建聊天账号失败,请稍后再试"); // } Map result = new HashMap<>(); - result.put("info", tempModel); + StpUtil.login(tempModel.getId()); + UserModelVO userModelVO = BeanUtil.copyProperties(tempModel, UserModelVO.class); + userModelVO.setToken(StpUtil.getTokenValue()); + result.put("info", userModelVO); result.put("newAccount",false); //否则直接返回用户 return ResponseData.success(result); @@ -149,7 +155,10 @@ public class UserController { UserModel model = userDao.queryWithPhoneNumber(phoneNumber); Map result = new HashMap<>(); if (model != null) { // 老用户 - result.put("info",model); + UserModelVO userModelVO = BeanUtil.copyProperties(model, UserModelVO.class); + StpUtil.login(userModelVO.getId()); + userModelVO.setToken(StpUtil.getTokenValue()); + result.put("info",userModelVO); result.put("newAccount", false); result.put("chatInfo",wxChatParam); return ResponseData.success(result); @@ -197,7 +206,9 @@ public class UserController { @PostMapping("getUserInfo") public ResponseData getUserInfo(@RequestBody Map map) { UserModel userModel = userDao.selectById(map.get("id")); - return ResponseData.success(userModel); + UserModelVO userModelVO = BeanUtil.copyProperties(userModel, UserModelVO.class); + userModelVO.setHavaPassword(userModel.getPassword() != null); + return ResponseData.success(userModelVO); } // 查询用户所有pk数据 @@ -394,4 +405,27 @@ public class UserController { public ResponseData verificationMail(@RequestParam("token") String token){ return ResponseData.success(userService.verificationMail(token)); } + + + @GetMapping("/qrcode") + public ResponseData generatedQrcode(){ + return ResponseData.success(userService.generatedQrcode()); + } + + @GetMapping("/check/{uuid}") + public ResponseData checkQrcode(@PathVariable String uuid){ + return ResponseData.success(userService.checkQrcode(uuid)); + } + + @PostMapping("/scan") + public ResponseData scanQrCode(@RequestBody ScanInfoDTO scanInfoDTO) { + userService.scanQrcode(scanInfoDTO); + return ResponseData.success(""); + } + + @PostMapping("/confirm") + public ResponseData confirm(@RequestBody ScanInfoDTO scanInfoDTO) { + userService.confirm(scanInfoDTO); + return ResponseData.success(""); + } } diff --git a/src/main/java/vvpkassistant/User/model/DTO/LoginInfoDTO.java b/src/main/java/vvpkassistant/User/model/DTO/LoginInfoDTO.java new file mode 100644 index 0000000..4f70a20 --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/DTO/LoginInfoDTO.java @@ -0,0 +1,29 @@ +package vvpkassistant.User.model.DTO; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class LoginInfoDTO { + + /** + * 唯一标识 + */ + private String uuid; + /** + * 设备号 + */ + private String device; + + /** + * 扫码状态 + */ + private String status; + + private Integer userId; +} \ No newline at end of file diff --git a/src/main/java/vvpkassistant/User/model/DTO/ScanInfoDTO.java b/src/main/java/vvpkassistant/User/model/DTO/ScanInfoDTO.java new file mode 100644 index 0000000..59a17c4 --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/DTO/ScanInfoDTO.java @@ -0,0 +1,13 @@ +package vvpkassistant.User.model.DTO; + +import lombok.Data; + +/* + * @author: ziin + * @date: 2025/8/5 16:43 + */ +@Data +public class ScanInfoDTO { + private String uuid; + private Integer userId; +} diff --git a/src/main/java/vvpkassistant/User/model/QrcodeEntity.java b/src/main/java/vvpkassistant/User/model/QrcodeEntity.java new file mode 100644 index 0000000..dfd2215 --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/QrcodeEntity.java @@ -0,0 +1,13 @@ +package vvpkassistant.User.model; + +import lombok.Data; + +/* + * @author: ziin + * @date: 2025/8/5 20:06 + */ +@Data +public class QrcodeEntity { + private String uuid; + private String type; +} diff --git a/src/main/java/vvpkassistant/User/model/QrcodeVO.java b/src/main/java/vvpkassistant/User/model/QrcodeVO.java new file mode 100644 index 0000000..c17290e --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/QrcodeVO.java @@ -0,0 +1,15 @@ +package vvpkassistant.User.model; + +import lombok.Builder; +import lombok.Data; + +/* + * @author: ziin + * @date: 2025/8/5 18:14 + */ +@Data +@Builder +public class QrcodeVO { + private String uuid; + private String qrcode; +} diff --git a/src/main/java/vvpkassistant/User/model/ResponseVO.java b/src/main/java/vvpkassistant/User/model/ResponseVO.java new file mode 100644 index 0000000..a3cf16b --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/ResponseVO.java @@ -0,0 +1,32 @@ +package vvpkassistant.User.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ResponseVO { + + /** + * 唯一标识 + */ + private String uuid; + /** + * 登录二维码 + */ + private String qrcode; + + /** + * jwt令牌 + */ + private String token; + + /** + * 扫码状态 + */ + private String status; +} \ No newline at end of file diff --git a/src/main/java/vvpkassistant/User/model/UserModelVO.java b/src/main/java/vvpkassistant/User/model/UserModelVO.java index cbda940..27bc72d 100644 --- a/src/main/java/vvpkassistant/User/model/UserModelVO.java +++ b/src/main/java/vvpkassistant/User/model/UserModelVO.java @@ -23,5 +23,6 @@ public class UserModelVO { private String token; private Boolean newAccount; private WxChatParam chatInfo; + private Boolean havaPassword; private Integer mailVerification; } diff --git a/src/main/java/vvpkassistant/User/model/enumeration/LoginStatusEnum.java b/src/main/java/vvpkassistant/User/model/enumeration/LoginStatusEnum.java new file mode 100644 index 0000000..476add8 --- /dev/null +++ b/src/main/java/vvpkassistant/User/model/enumeration/LoginStatusEnum.java @@ -0,0 +1,17 @@ +package vvpkassistant.User.model.enumeration; + +import lombok.Getter; + +@Getter +public enum LoginStatusEnum { + UNSCANNED("未扫描"), + SCANNED("已扫描"), + CONFIRMED("已确认"); + + private String desc; + + + LoginStatusEnum(String desc) { + this.desc = desc; + } +} \ No newline at end of file diff --git a/src/main/java/vvpkassistant/User/service/UserService.java b/src/main/java/vvpkassistant/User/service/UserService.java index 044e53a..fecd2ea 100644 --- a/src/main/java/vvpkassistant/User/service/UserService.java +++ b/src/main/java/vvpkassistant/User/service/UserService.java @@ -1,6 +1,7 @@ package vvpkassistant.User.service; import com.baomidou.mybatisplus.extension.service.IService; +import vvpkassistant.User.model.DTO.ScanInfoDTO; import vvpkassistant.User.model.DTO.UserModelDTO; import vvpkassistant.User.model.UserModel; import vvpkassistant.User.model.UserModelVO; @@ -21,4 +22,12 @@ public interface UserService extends IService { Boolean activateAccount(String token); Boolean verificationMail(String token); + + Object generatedQrcode(); + + Object checkQrcode(String uuid); + + void scanQrcode(ScanInfoDTO scanInfoDTO); + + void confirm(ScanInfoDTO scanInfoDTO); } diff --git a/src/main/java/vvpkassistant/User/service/UserServiceImpl.java b/src/main/java/vvpkassistant/User/service/UserServiceImpl.java index 228aaf7..c19481c 100644 --- a/src/main/java/vvpkassistant/User/service/UserServiceImpl.java +++ b/src/main/java/vvpkassistant/User/service/UserServiceImpl.java @@ -3,28 +3,41 @@ package vvpkassistant.User.service; import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.temp.SaTempUtil; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.lang.UUID; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.google.zxing.WriterException; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import vvpkassistant.Data.WxChatParam; import vvpkassistant.Tools.BcryptUtils; +import vvpkassistant.Tools.QRCodeUtil; import vvpkassistant.Tools.VVTools; import vvpkassistant.User.mapper.UserDao; +import vvpkassistant.User.model.*; +import vvpkassistant.User.model.DTO.LoginInfoDTO; +import vvpkassistant.User.model.DTO.ScanInfoDTO; import vvpkassistant.User.model.DTO.UserModelDTO; -import vvpkassistant.User.model.UserModel; -import vvpkassistant.User.model.UserModelVO; +import vvpkassistant.User.model.enumeration.LoginStatusEnum; import vvpkassistant.common.ErrorCode; import vvpkassistant.exception.BusinessException; import vvpkassistant.mail.service.MailService; import javax.annotation.Resource; +import java.io.IOException; +import java.util.Objects; +import java.util.concurrent.TimeUnit; /* * @author: ziin * @date: 2025/8/4 16:19 */ @Service +@Slf4j public class UserServiceImpl extends ServiceImpl implements UserService { @Resource @@ -35,6 +48,11 @@ public class UserServiceImpl extends ServiceImpl implements @Autowired private MailService mailService; + + private final Cache qrcodeCache = Caffeine.newBuilder() + .expireAfterWrite(2, TimeUnit.MINUTES) + .build(); + @Override public UserModelVO loginWithMail(UserModelDTO model) { @@ -164,4 +182,74 @@ public class UserServiceImpl extends ServiceImpl implements } throw new BusinessException(ErrorCode.SYSTEM_ERROR,"邮箱验证失败"); } + + @Override + public QrcodeVO generatedQrcode() { + String uuid = UUID.randomUUID().toString(); + QrcodeEntity qrcodeEntity = new QrcodeEntity(); + qrcodeEntity.setUuid(uuid); + qrcodeEntity.setType("qrcdoe"); + String base64QR = null; + try { + base64QR = QRCodeUtil.generateQRCode(JSONUtil.toJsonStr(qrcodeEntity), 200, 200); + } catch (WriterException | IOException e) { + log.error(e.getMessage()); + throw new BusinessException(ErrorCode.SYSTEM_ERROR,"二维码生成失败"); + } + + LoginInfoDTO loginInfoDTO = new LoginInfoDTO(); + loginInfoDTO.setStatus(LoginStatusEnum.UNSCANNED.name()); + loginInfoDTO.setUuid(uuid); + + // 二维码uuid绑定,存入缓存 + qrcodeCache.put(uuid,loginInfoDTO); + // 返回生成的二维码信息 + QrcodeVO vo = QrcodeVO.builder().uuid(uuid).qrcode("data:image/png;base64," + base64QR).build(); + log.info("-------生成二维码成功:{}-------", uuid); + return vo; + } + + @Override + public Object checkQrcode(String uuid) { + LoginInfoDTO loginInfoDTO = qrcodeCache.getIfPresent(uuid); + if (loginInfoDTO == null) { + throw new BusinessException(ErrorCode.QRCODE_EXPIRED); + } + if (Objects.equals(loginInfoDTO.getStatus(), LoginStatusEnum.SCANNED.name())) { + return loginInfoDTO; + } + if (LoginStatusEnum.CONFIRMED.name().equals(loginInfoDTO.getStatus())) { + UserModel userModel = userDao.selectById(loginInfoDTO.getUserId()); + StpUtil.login(userModel.getId()); + UserModelVO userModelVO = BeanUtil.copyProperties(userModel, UserModelVO.class); + userModelVO.setToken(StpUtil.getTokenValue()); + userModelVO.setChatInfo(wxChatParam); + return userModelVO; + } + return null; + } + + @Override + public void scanQrcode(ScanInfoDTO scanInfoDTO) { + LoginInfoDTO loginInfoDTO = qrcodeCache.getIfPresent(scanInfoDTO.getUuid()); + if (loginInfoDTO != null) { + loginInfoDTO.setStatus(LoginStatusEnum.SCANNED.name()); + } + if (loginInfoDTO != null) { + qrcodeCache.put(scanInfoDTO.getUuid(),loginInfoDTO); + } + + log.info("-------扫码成功uuid:{}-------", scanInfoDTO.getUuid()); + } + + @Override + public void confirm(ScanInfoDTO scanInfoDTO) { + LoginInfoDTO loginInfoDTO = qrcodeCache.getIfPresent(scanInfoDTO.getUuid()); + if (loginInfoDTO != null) { + loginInfoDTO.setStatus(LoginStatusEnum.CONFIRMED.name()); + loginInfoDTO.setUserId(scanInfoDTO.getUserId()); + qrcodeCache.put(scanInfoDTO.getUuid(),loginInfoDTO); + } + log.info("-------确认登录成功uuid:{}-------", scanInfoDTO.getUuid()); + } } diff --git a/src/main/java/vvpkassistant/common/ErrorCode.java b/src/main/java/vvpkassistant/common/ErrorCode.java index d6f23aa..65c033e 100644 --- a/src/main/java/vvpkassistant/common/ErrorCode.java +++ b/src/main/java/vvpkassistant/common/ErrorCode.java @@ -16,6 +16,7 @@ public enum ErrorCode { CONFIG_NAME_DUPLICATE(1004, "配置名称重复"), SIGN_IN_FAIL(1004, "当天已签到"), EMAIL_SEND_FREQUENT(1005,"邮件发送太频繁,请 1 分钟后再试"), + QRCODE_EXPIRED(1006,"二维码已过期"), /* =============== 主播相关 =============== */ ANCHOR_ALREADY_EXISTS(2001, "主播已存在"), diff --git a/src/main/java/vvpkassistant/config/SaTokenConfigure.java b/src/main/java/vvpkassistant/config/SaTokenConfigure.java index f984cff..e269c02 100644 --- a/src/main/java/vvpkassistant/config/SaTokenConfigure.java +++ b/src/main/java/vvpkassistant/config/SaTokenConfigure.java @@ -45,7 +45,14 @@ public class SaTokenConfigure implements WebMvcConfigurer { "/user/loginWithPhoneNumber", "/user/registerWithMail", "/user/loginWithMail", - "/user/activate" + "/user/inputUserInfo", + "/user/verificationMail", + "/user/activate", + "/user/qrcode", + "/user/check/*", + "/user/scan", + "/user/confirm" + }; } diff --git a/target/classes/application.yml b/target/classes/application.yml index f69cce0..054a339 100644 --- a/target/classes/application.yml +++ b/target/classes/application.yml @@ -30,9 +30,9 @@ sa-token: # token 名称(同时也是 cookie 名称) token-name: token # token 有效期(单位:秒) 默认30天,-1 代表永久有效 - timeout: 2592000 + timeout: -1 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 - active-timeout: -1 + active-timeout: 648000 # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) is-concurrent: true # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token) @@ -42,4 +42,5 @@ sa-token: # 是否输出操作日志 is-log: true -activateUrl: http://192.168.1.174:8086/user/activate?token= \ No newline at end of file +activateUrl: http://192.168.1.174:8086/user/activate?token= +verificationMailUrl: http://192.168.1.174:8086/user/verification?token= \ No newline at end of file