From ccb7f885eb7f8bad222d47081d7a8fc8e1203e7a Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Tue, 22 Apr 2025 12:24:38 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E4=B8=BB=E5=88=86=E6=94=AF=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/1schema.sql | 2 +- .../admin/controller/SysDeptController.java | 15 ++++++++++++ .../pjcloud/admin/service/SysDeptService.java | 2 ++ .../service/impl/SysDeptServiceImpl.java | 24 +++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/db/1schema.sql b/db/1schema.sql index 982376e44..c9fef6a74 100644 --- a/db/1schema.sql +++ b/db/1schema.sql @@ -33,6 +33,6 @@ create database `pjcloudx_thirdparty` default character set utf8mb4 collate utf8 create database `pjcloudx_canteen` default character set utf8mb4 collate utf8mb4_general_ci; create database `pjcloudx_erp` default character set utf8mb4 collate utf8mb4_general_ci; create database `pjcloudx_supermarket` default character set utf8mb4 collate utf8mb4_general_ci; -create database `pjcloudx_supermarket_erp` default character set utf8mb4 collate utf8mb4_general_ci; +create database `pjcloudx_integrated` default character set utf8mb4 collate utf8mb4_general_ci; create database `pjcloudx_wallet` default character set utf8mb4 collate utf8mb4_general_ci; create database `pjcloudx_hardware` default character set utf8mb4 collate utf8mb4_general_ci; diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysDeptController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysDeptController.java index 065482f31..b635c5a71 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysDeptController.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysDeptController.java @@ -91,6 +91,21 @@ public class SysDeptController { return R.ok(sysDeptService.selectTree(deptName, parentId)); } + + /** + * + * 查询所有,无权限过滤 + * simpleTree + * @param deptName + * @param parentId + * @return + */ + @GetMapping(value = "/simpleTree") + public R getSimpleTree(String deptName, Long parentId) { + return R.ok(sysDeptService.selectSimpleTree(deptName, parentId)); + } + + /** * 添加 * diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysDeptService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysDeptService.java index 94ba43d45..c14f20d38 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysDeptService.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysDeptService.java @@ -50,6 +50,8 @@ public interface SysDeptService extends IService { */ List> selectTree(String deptName, Long parentId); + List> selectSimpleTree(String deptName, Long parentId); + /** * 删除部门 * diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysDeptServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysDeptServiceImpl.java index e36155178..ab917719c 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysDeptServiceImpl.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysDeptServiceImpl.java @@ -177,6 +177,30 @@ public class SysDeptServiceImpl extends ServiceImpl impl return TreeUtil.build(collect, parentId == null ? 0 : parentId); } + @Override + public List> selectSimpleTree(String deptName, Long parentId) { + // 查询全部部门 + List deptAllList = deptMapper + .selectList(Wrappers.lambdaQuery().like(StrUtil.isNotBlank(deptName), SysDept::getName, deptName)); + + List> collect = deptAllList.stream() + .filter(dept -> dept.getDeptId().intValue() != dept.getParentId()) + .sorted(Comparator.comparingInt(SysDept::getSortOrder)) + .map(dept -> { + TreeNode treeNode = new TreeNode<>(); + treeNode.setId(dept.getDeptId()); + treeNode.setParentId(dept.getParentId()); + treeNode.setName(dept.getName()); + return treeNode; + }) + .collect(Collectors.toList()); + + List> build = TreeUtil.build(collect, parentId == null ? 0 : parentId); + + return build; + + } + /** * 导出部门 * From 4aa5b7310cb6cff4605653a021d7f95223a8f37a Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Tue, 22 Apr 2025 13:00:18 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E9=83=A8=E9=97=A8id?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pjcloud/admin/api/vo/SimpleUserListVO.java | 15 +++++++++++++++ .../admin/controller/SysUserController.java | 17 +++++++++++++---- .../pjcloud/admin/service/SysUserService.java | 14 ++++++++++---- .../admin/service/impl/SysUserServiceImpl.java | 10 ++++++++++ 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/SimpleUserListVO.java diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/SimpleUserListVO.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/SimpleUserListVO.java new file mode 100644 index 000000000..bebf8a741 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/SimpleUserListVO.java @@ -0,0 +1,15 @@ +package com.bsd.pjcloud.admin.api.vo; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "简要用户信息,不包含手机号") +public class SimpleUserListVO { + + private Long userId; + + @Schema(description = "姓名") + private String name; +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java index 6fc912117..9ea76e0d2 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java @@ -29,10 +29,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.bsd.pjcloud.admin.api.dto.UserDTO; import com.bsd.pjcloud.admin.api.dto.UserInfo; import com.bsd.pjcloud.admin.api.entity.SysUser; -import com.bsd.pjcloud.admin.api.vo.SimpleUserAllListVO; -import com.bsd.pjcloud.admin.api.vo.UserExcelFaceVo; -import com.bsd.pjcloud.admin.api.vo.UserExcelVO; -import com.bsd.pjcloud.admin.api.vo.UserVO; +import com.bsd.pjcloud.admin.api.vo.*; import com.bsd.pjcloud.admin.service.SysUserService; import com.bsd.pjcloud.common.core.constant.CommonConstants; import com.bsd.pjcloud.common.core.exception.ErrorCodes; @@ -360,6 +357,18 @@ public class SysUserController { return R.ok(userService.listUserIdByDeptIds(CollUtil.toList(deptIdList))); } + /** + * 根据部门id查询用户列表 + * @param deptId + * @return + */ +// @Inner + @GetMapping("/getUserIdListByDeptId") + public R> getUserIdListByDeptId(@RequestParam("deptId")Long deptId, + @RequestParam(value = "name",required = false) String name) { + return R.ok(userService.listUserIdByDeptId(deptId,name)); + } + /** * 根据用户名获取用户列表 * diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java index cfaa7d60e..79890825c 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/SysUserService.java @@ -26,10 +26,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.bsd.pjcloud.admin.api.dto.UserDTO; import com.bsd.pjcloud.admin.api.dto.UserInfo; import com.bsd.pjcloud.admin.api.entity.SysUser; -import com.bsd.pjcloud.admin.api.vo.SimpleUserAllListVO; -import com.bsd.pjcloud.admin.api.vo.UserExcelFaceVo; -import com.bsd.pjcloud.admin.api.vo.UserExcelVO; -import com.bsd.pjcloud.admin.api.vo.UserVO; +import com.bsd.pjcloud.admin.api.vo.*; import com.bsd.pjcloud.common.core.util.R; import com.bsd.pjcloud.flow.task.dto.ProcessNodeRecordAssignUserParamDto; @@ -221,4 +218,13 @@ public interface SysUserService extends IService { * @return */ List listScopeByLikeNameOrByMobileScope(LambdaQueryWrapper eq); + + + /** + * 根据部门id/姓名,获取用户信息 + * @param deptId + * @param name + * @return + */ + List listUserIdByDeptId(Long deptId, String name); } diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java index 420e03e23..6e8bf6623 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserServiceImpl.java @@ -915,4 +915,14 @@ public class SysUserServiceImpl extends ServiceImpl impl private SysUserServiceImpl getSelf() { return SpringUtil.getBean(getClass()); } + + + + public List listUserIdByDeptId(Long deptId, String name) { + List sysUsers = baseMapper.selectList(Wrappers.lambdaQuery() + .eq(SysUser::getDeptId, deptId) + .like(StrUtil.isNotBlank(name),SysUser::getName, name)); + return com.bsd.pjcloud.common.core.util.BeanUtils.toBean(sysUsers, SimpleUserListVO.class); + } + } From 06167dd9e9cc5d598e8ea9c0e8169ce5c15d0ebb Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Tue, 22 Apr 2025 15:29:17 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=9F=AD=E4=BF=A1?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=A2=9E=E5=8A=A0=E9=98=B2=E5=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feign/RemoterThirdPartySmsService.java | 48 +++++++++++ .../pjcloud-thirdparty-biz/pom.xml | 4 + .../thirdparty/controller/SmsController.java | 15 ++-- .../controller/ThirdPartyOAth2Cotroller.java | 32 +++++++- .../thirdparty/service/SmsService.java | 79 ++++++++++++++++++- .../pjcloud/thirdparty/utils/SmsCodeUtil.java | 75 ++++++++++++++++++ 6 files changed, 240 insertions(+), 13 deletions(-) create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterThirdPartySmsService.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/SmsCodeUtil.java diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterThirdPartySmsService.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterThirdPartySmsService.java new file mode 100644 index 000000000..2dff4ba9d --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterThirdPartySmsService.java @@ -0,0 +1,48 @@ +/* + * + * Copyright (c) 2018-2025, pjcloud All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: pjcloud + * + */ + +package com.bsd.pjcloud.thirdparty.api.feign; + +import com.bsd.pjcloud.common.core.constant.ServiceNameConstants; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.feign.annotation.NoToken; +import com.bsd.pjcloud.thirdparty.entity.ThirdPartyUserEntity; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; +import java.util.Map; + +@FeignClient(contextId = "remoterThirdPartySmsService", value = ServiceNameConstants.THIRDPARTY_SERVICE) +public interface RemoterThirdPartySmsService { + + // 简单发送 + @PostMapping("/sendMsg") + public void sendSimpleMsg(@RequestParam String mobile, @RequestParam String templateId, @RequestParam("clientIp") String clientIp); + + // 带参数发送 + @PostMapping("/sendMsgParams") + public void sendParamsMsg( + @RequestParam("mobile") String mobile,@RequestParam("templateId") String templateId, + @RequestBody Map params,@RequestParam("clientIp") String clientIp); +} diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml b/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml index 34dfa75ed..c0e8c3e3e 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml @@ -42,6 +42,10 @@ com.bsd pjcloud-common-data + + com.bsd + + com.bsd diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/SmsController.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/SmsController.java index 7be7fbc35..6b52a7a17 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/SmsController.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/SmsController.java @@ -2,6 +2,7 @@ package com.bsd.pjcloud.thirdparty.controller; import com.bsd.pjcloud.common.security.annotation.Inner; import com.bsd.pjcloud.thirdparty.service.SmsService; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -12,22 +13,22 @@ import java.util.Map; @RequiredArgsConstructor public class SmsController { + private final SmsService smsService; // 简单发送 @PostMapping("/sendMsg") - public void sendVerifyCode(@RequestParam String mobile) { - smsService.sendSms(mobile, "20657"); + public void sendSimpleMsg(@RequestParam String mobile,@RequestParam String templateId,@RequestParam("clientIp") String clientIp) { + smsService.sendSms(mobile, templateId,clientIp); } // 带参数发送 @PostMapping("/sendMsgParams") @Inner(value = false) - public void sendOrderNotify( - @RequestParam String mobile, - @RequestBody Map params - ) { - smsService.sendSms(mobile, "20657", params); + public void sendParamsMsg( + @RequestParam("mobile") String mobile, @RequestParam("templateId") String templateId, + @RequestBody Map params, @RequestParam("clientIp") String clientIp) { + smsService.sendSms(mobile, templateId, params,clientIp); } } \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java index db8811776..c6ce8cb0f 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java @@ -7,32 +7,36 @@ import com.bsd.pjcloud.admin.api.entity.SysUser; import com.bsd.pjcloud.admin.api.feign.RemoteTokenService; import com.bsd.pjcloud.admin.api.feign.RemoteUserService; import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.core.util.WebUtils; import com.bsd.pjcloud.common.log.annotation.SysLog; import com.bsd.pjcloud.common.security.annotation.Inner; import com.bsd.pjcloud.thirdparty.dto.SHJNSSODTO; import com.bsd.pjcloud.thirdparty.dto.UrlTokenDTO; import com.bsd.pjcloud.thirdparty.dto.ZZDUserDTO; import com.bsd.pjcloud.thirdparty.entity.ThirdPartyUserEntity; +import com.bsd.pjcloud.thirdparty.service.SmsService; import com.bsd.pjcloud.thirdparty.service.ThirdPartyOAuth2Service; import com.bsd.pjcloud.thirdparty.service.ThirdPartyUserService; +import com.bsd.pjcloud.thirdparty.utils.SmsCodeUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.apache.seata.spring.annotation.GlobalTransactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpHeaders; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; +import java.util.concurrent.TimeUnit; @RestController @RequiredArgsConstructor @@ -49,6 +53,9 @@ public class ThirdPartyOAth2Cotroller { private final ThirdPartyUserService thirdPartyUserService; + private final SmsService smsService; + @Autowired + private RedisTemplate redisTemplate; // @Operation(summary = "浙政钉token" ) // @GetMapping("/zzd/sso" ) @@ -257,4 +264,21 @@ public class ThirdPartyOAth2Cotroller { } + + @PostMapping("/loginSms") + @Operation(summary = "短信登录认证") + @SysLog("短信登录认证") + @Inner(value = false) + public R loginSms(@RequestParam String mobilePhone) { + Map stringHashMap = new LinkedHashMap<>(); + String s = SmsCodeUtil.generateNumberCode(6); + stringHashMap.put("code",s); + stringHashMap.put("date","5"); + smsService.sendSms(mobilePhone, "20657",stringHashMap, WebUtils.getIP()); + + redisTemplate.opsForSet().add("smsCode_"+mobilePhone,s, 5, TimeUnit.MINUTES); + return R.ok(); + } + + } diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/SmsService.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/SmsService.java index e82f0ac20..24598d9c6 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/SmsService.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/SmsService.java @@ -5,12 +5,16 @@ import com.bsd.pjcloud.thirdparty.config.SmsConfig; import com.bsd.pjcloud.thirdparty.dto.sms.SmsRequest; import com.bsd.pjcloud.thirdparty.dto.sms.SmsResponse; import com.bsd.pjcloud.thirdparty.exception.SmsException; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; @Service @RequiredArgsConstructor @@ -19,13 +23,30 @@ public class SmsService { private final SmsConfig config; private final SmsHttpClient httpClient; + @Autowired + private RedisTemplate redisTemplate; + private static final String SMS_IP_LIMIT_PREFIX = "sms:ip_limit:"; + private static final String SMS_LIMIT_PREFIX = "sms:limit:"; + + /** + * 同一个ip,一分钟内只能请求五次 + */ + private static final int MAX_IP_REQUESTS = 5; + private static final int IP_LIMIT_EXPIRE_SECONDS = 60; + + private static final int LIMIT_EXPIRE_SECONDS = 60; + /** * 发送短信(最简版) * @param mobile 手机号 * @param templateId 模板ID */ - public void sendSms(String mobile, String templateId) { + public void sendSms(String mobile, String templateId, String clientIp) { validateMobile(mobile); + // IP限流检查 + checkIpLimit(clientIp); + + checkPhoneLimit(mobile); SmsConfig.TemplateConfig template = getTemplate(templateId); if (!template.getParams().isEmpty()) { @@ -41,8 +62,15 @@ public class SmsService { * @param templateId 模板ID * @param params 参数Map */ - public void sendSms(String mobile, String templateId, Map params) { + public void sendSms(String mobile, String templateId, Map params,String clientIp) { validateMobile(mobile); + //todo redisson分布式形式检查 + +// IP限流检查 + checkIpLimit(clientIp); + + checkPhoneLimit(mobile); + SmsConfig.TemplateConfig template = getTemplate(templateId); String content = replacePlaceholders(template.getContent(), params, template.getParams()); @@ -95,8 +123,55 @@ public class SmsService { } private void validateMobile(String mobile) { + if (!mobile.matches("^1[3-9]\\d{9}$")) { throw new SmsException("无效的手机号码: " + mobile); } } + + private void checkIpLimit(String clientIp) { + String ipLimitKey = SMS_IP_LIMIT_PREFIX + clientIp; + Long requestCount = redisTemplate.opsForValue().increment(ipLimitKey); + + if (requestCount == 1) { + // 首次设置时添加过期时间 + redisTemplate.expire(ipLimitKey, IP_LIMIT_EXPIRE_SECONDS, TimeUnit.SECONDS); + } + + if (requestCount != null && requestCount > MAX_IP_REQUESTS) { + throw new RuntimeException("当前IP请求过于频繁,请稍后再试"); + } + } + + private void checkPhoneLimit(String phoneNumber) { + String limitKey = SMS_LIMIT_PREFIX + phoneNumber; + if (Boolean.TRUE.equals(redisTemplate.hasKey(limitKey))) { + throw new RuntimeException("手机号操作过于频繁,请稍后再试"); + } + redisTemplate.opsForValue().set(limitKey, "1", LIMIT_EXPIRE_SECONDS, TimeUnit.SECONDS); + } + + + + private String getClientIp(HttpServletRequest request) { + String[] headersToCheck = { + "X-Forwarded-For", + "Proxy-Client-IP", + "WL-Proxy-Client-IP", + "HTTP_CLIENT_IP", + "HTTP_X_FORWARDED_FOR" + }; + + // 遍历代理头 + for (String header : headersToCheck) { + String ip = request.getHeader(header); + if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) { + return ip.split(",")[0].trim(); // 处理多级代理 + } + } + + // 最终回退方案 + return request.getRemoteAddr(); + } + } \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/SmsCodeUtil.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/SmsCodeUtil.java new file mode 100644 index 000000000..5385baa72 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/SmsCodeUtil.java @@ -0,0 +1,75 @@ +package com.bsd.pjcloud.thirdparty.utils; + +import java.security.SecureRandom; +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * 短信验证码生成工具类 + */ +public class SmsCodeUtil { + + // 数字字符集 + private static final String NUMERIC_CHARS = "0123456789"; + + // 字母数字字符集(排除易混淆字符) + private static final String ALPHANUMERIC_CHARS = + "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz"; + + // 使用安全随机数生成器 + private static final SecureRandom random = new SecureRandom(); + + /** + * 生成6位纯数字验证码 + */ + public static String generateNumericCode() { + return generateCustomCode(6, NUMERIC_CHARS); + } + + /** + * 生成6位字母数字验证码(排除易混淆字符) + */ + public static String generateAlphanumericCode() { + return generateCustomCode(6, ALPHANUMERIC_CHARS); + } + + /** + * 自定义验证码生成 + * @param length 验证码长度 + * @param charSet 使用的字符集 + */ + public static String generateCustomCode(int length, String charSet) { + if (length < 1) throw new IllegalArgumentException("验证码长度不能小于1"); + if (charSet == null || charSet.isEmpty()) { + throw new IllegalArgumentException("字符集不能为空"); + } + + return IntStream.range(0, length) + .map(i -> random.nextInt(charSet.length())) + .mapToObj(charSet::charAt) + .collect(Collectors.collectingAndThen( + Collectors.toList(), + list -> { + Collections.shuffle(list); + return list.stream(); + } + )) + .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) + .toString(); + } + + /** + * 旧版本兼容:生成指定位数的纯数字验证码 + * @param length 验证码长度 (4-9) + */ + public static String generateNumberCode(int length) { + if (length < 4 || length > 9) { + throw new IllegalArgumentException("验证码长度需在4-9位之间"); + } + + int min = (int) Math.pow(10, length - 1); + int max = (int) Math.pow(10, length) - 1; + return String.valueOf(min + random.nextInt(max - min)); + } +} \ No newline at end of file From aa5281da83fc6190f9e90de0ce48e3591b52ed4e Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Tue, 22 Apr 2025 17:34:30 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=8C=87=E7=BA=B9?= =?UTF-8?q?=E5=BC=95=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ThirdPartyOAth2Cotroller.java | 43 ++++++- .../utils/DeviceFingerprintUtil.java | 14 +++ .../api/entity/UserTrustedDeviceEntity.java | 95 ++++++++++++++ .../UserTrustedDeviceController.java | 118 ++++++++++++++++++ .../admin/mapper/UserTrustedDeviceMapper.java | 11 ++ .../service/UserTrustedDeviceService.java | 8 ++ .../impl/UserTrustedDeviceServiceImpl.java | 16 +++ .../mapper/UserTrustedDeviceMapper.xml | 19 +++ 8 files changed, 319 insertions(+), 5 deletions(-) create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/DeviceFingerprintUtil.java create mode 100644 pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/UserTrustedDeviceEntity.java create mode 100644 pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/UserTrustedDeviceController.java create mode 100644 pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/UserTrustedDeviceMapper.java create mode 100644 pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/UserTrustedDeviceService.java create mode 100644 pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/UserTrustedDeviceServiceImpl.java create mode 100644 pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/UserTrustedDeviceMapper.xml diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java index c6ce8cb0f..fca8dc49a 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java @@ -17,6 +17,7 @@ import com.bsd.pjcloud.thirdparty.entity.ThirdPartyUserEntity; import com.bsd.pjcloud.thirdparty.service.SmsService; import com.bsd.pjcloud.thirdparty.service.ThirdPartyOAuth2Service; import com.bsd.pjcloud.thirdparty.service.ThirdPartyUserService; +import com.bsd.pjcloud.thirdparty.utils.DeviceFingerprintUtil; import com.bsd.pjcloud.thirdparty.utils.SmsCodeUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -203,20 +204,21 @@ public class ThirdPartyOAth2Cotroller { @Transactional @GlobalTransactional public R shjnsso(@RequestBody @Valid SHJNSSODTO shjnsso) { + //检查设备指纹 ZZDUserDTO zzdUserDTO = thirdPartyOAuth2Service.shjnsso(shjnsso.getAccountId(), shjnsso.getSessionId()); if (null==zzdUserDTO){ throw new RuntimeException(""); } ZZDUserDTO.Ext ext = zzdUserDTO.getExt(); String mobile = zzdUserDTO.getMobile(); - R r; R> userByMobileOrEmployeeCode = remoteUserService.getUserByMobileOrEmployeeCode(null, mobile); List sysUserList = userByMobileOrEmployeeCode.getData(); if(!CollectionUtils.isEmpty(sysUserList)){ //登录成功生成token UserTokenDTO userTokenDTO = new UserTokenDTO(); userTokenDTO.setSysUser(sysUserList.get(0)); - r=remoteTokenService.generateToken(userTokenDTO); + + return remoteTokenService.generateToken(userTokenDTO); }else { //自动注册 // UserDTO userDTO = new UserDTO(); @@ -237,10 +239,25 @@ public class ThirdPartyOAth2Cotroller { // r=remoteTokenService.generateToken(userTokenDTO); return R.failed("系统中没有当前用户信息,请联系管理员进行申请!"); } - return r; + } - + // 在shjnsso方法中添加验证 +// @PostMapping("/shjnsso") +// public R shjnsso(..., HttpServletRequest request) { +// // 设备指纹验证 +// String clientFingerprint = DeviceFingerprintUtil.generate(request); +// String storedFingerprint = redisTemplate.opsForValue().get("device_fp:" + shjnsso.getAccountId()); +// +// if (!clientFingerprint.equals(storedFingerprint)) { +// // 新设备需要短信验证 +// String code = SmsCodeUtil.generateNumberCode(6); +// smsService.sendSms(mobile, "验证码模板ID", Map.of("code", code)); +// return R.failed("new_device").data("needSmsVerify", true); +// } +// +// // 原有逻辑继续执行... +// } @Inner(value = false) @GetMapping("/getAuthToken/{token}") public R info(@PathVariable(name = "token") String token) { @@ -269,14 +286,30 @@ public class ThirdPartyOAth2Cotroller { @Operation(summary = "短信登录认证") @SysLog("短信登录认证") @Inner(value = false) - public R loginSms(@RequestParam String mobilePhone) { + public R loginSms(@RequestParam String mobilePhone,HttpServletRequest httpServletRequest) { Map stringHashMap = new LinkedHashMap<>(); String s = SmsCodeUtil.generateNumberCode(6); stringHashMap.put("code",s); stringHashMap.put("date","5"); + System.out.println(WebUtils.getIP()); + System.out.println(WebUtils.getIP(httpServletRequest)); smsService.sendSms(mobilePhone, "20657",stringHashMap, WebUtils.getIP()); redisTemplate.opsForSet().add("smsCode_"+mobilePhone,s, 5, TimeUnit.MINUTES); + + //记录信任的设备 + // 2. 记录信任设备 +// String deviceFingerprint = DeviceFingerprintUtil.generate(request); +// deviceService.addTrustedDevice( +// dto.getUserId(), +// deviceFingerprint, +// LocalDateTime.now().plusMonths(3) // 信任3个月 +// ); +// +// // 3. 生成令牌 +// User user = userService.getById(dto.getUserId()); +// String token = jwtService.generateToken(user); +// return R.ok().data("token", token); return R.ok(); } diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/DeviceFingerprintUtil.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/DeviceFingerprintUtil.java new file mode 100644 index 000000000..cbc193f2f --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/utils/DeviceFingerprintUtil.java @@ -0,0 +1,14 @@ +package com.bsd.pjcloud.thirdparty.utils; + +import com.bsd.pjcloud.common.core.util.WebUtils; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.util.DigestUtils; + +public class DeviceFingerprintUtil { + public static String generate(HttpServletRequest request) { + String userAgent = request.getHeader("User-Agent"); + String ip = WebUtils.getIP(request); + String accept = request.getHeader("Accept"); + return DigestUtils.md5DigestAsHex((userAgent + ip + accept).getBytes()); + } +} diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/UserTrustedDeviceEntity.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/UserTrustedDeviceEntity.java new file mode 100644 index 000000000..7e73beeb1 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/entity/UserTrustedDeviceEntity.java @@ -0,0 +1,95 @@ +package com.bsd.pjcloud.admin.api.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.time.LocalDateTime; + +/** + * 设备指纹 + * + * @author zjf + * @date 2025-04-22 17:14:57 + */ +@Data +@TableName("user_trusted_device") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "设备指纹") +public class UserTrustedDeviceEntity extends Model { + + + /** + * 主键ID + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description="主键ID") + private Long id; + + /** + * 用户id + */ + @Schema(description="用户id") + private Long userId; + + /** + * MD5 + */ + @Schema(description="MD5") + private String deviceFingerprint; + + /** + * 设备名称 + */ + @Schema(description="设备名称") + private String deviceName; + + /** + * 最后一次登录时间 + */ + @Schema(description="最后一次登录时间") + private LocalDateTime lastLoginTime; + + /** + * 过期时间 + */ + @Schema(description="过期时间") + private LocalDateTime expireTime; + + /** + * 创建人 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description="创建人") + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description="创建时间") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description="更新时间") + private String updateBy; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description="更新时间") + private LocalDateTime updateTime; + + /** + * 删除标记 + */ + @TableLogic + @TableField(fill = FieldFill.INSERT) + @Schema(description="删除标记") + private String delFlag; +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/UserTrustedDeviceController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/UserTrustedDeviceController.java new file mode 100644 index 000000000..3c2376ac1 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/UserTrustedDeviceController.java @@ -0,0 +1,118 @@ +package com.bsd.pjcloud.admin.controller; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import com.bsd.pjcloud.admin.api.entity.UserTrustedDeviceEntity; +import com.bsd.pjcloud.admin.service.UserTrustedDeviceService; +import org.springframework.security.access.prepost.PreAuthorize; +import com.bsd.pjcloud.common.excel.annotation.ResponseExcel; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.http.HttpHeaders; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 设备指纹 + * + * @author zjf + * @date 2025-04-22 17:14:57 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/userTrustedDevice" ) +@Tag(description = "userTrustedDevice" , name = "设备指纹管理" ) +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class UserTrustedDeviceController { + + private final UserTrustedDeviceService userTrustedDeviceService; + + /** + * 分页查询 + * @param page 分页对象 + * @param userTrustedDevice 设备指纹 + * @return + */ + @Operation(summary = "分页查询" , description = "分页查询" ) + @GetMapping("/page" ) + @PreAuthorize("@pms.hasPermission('admin_userTrustedDevice_view')" ) + public R getUserTrustedDevicePage(@ParameterObject Page page, @ParameterObject UserTrustedDeviceEntity userTrustedDevice) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + return R.ok(userTrustedDeviceService.page(page, wrapper)); + } + + + /** + * 通过id查询设备指纹 + * @param id id + * @return R + */ + @Operation(summary = "通过id查询" , description = "通过id查询" ) + @GetMapping("/{id}" ) + @PreAuthorize("@pms.hasPermission('admin_userTrustedDevice_view')" ) + public R getById(@PathVariable("id" ) Long id) { + return R.ok(userTrustedDeviceService.getById(id)); + } + + /** + * 新增设备指纹 + * @param userTrustedDevice 设备指纹 + * @return R + */ + @Operation(summary = "新增设备指纹" , description = "新增设备指纹" ) + @SysLog("新增设备指纹" ) + @PostMapping + @PreAuthorize("@pms.hasPermission('admin_userTrustedDevice_add')" ) + public R save(@RequestBody UserTrustedDeviceEntity userTrustedDevice) { + return R.ok(userTrustedDeviceService.save(userTrustedDevice)); + } + + /** + * 修改设备指纹 + * @param userTrustedDevice 设备指纹 + * @return R + */ + @Operation(summary = "修改设备指纹" , description = "修改设备指纹" ) + @SysLog("修改设备指纹" ) + @PutMapping + @PreAuthorize("@pms.hasPermission('admin_userTrustedDevice_edit')" ) + public R updateById(@RequestBody UserTrustedDeviceEntity userTrustedDevice) { + return R.ok(userTrustedDeviceService.updateById(userTrustedDevice)); + } + + /** + * 通过id删除设备指纹 + * @param ids id列表 + * @return R + */ + @Operation(summary = "通过id删除设备指纹" , description = "通过id删除设备指纹" ) + @SysLog("通过id删除设备指纹" ) + @DeleteMapping + @PreAuthorize("@pms.hasPermission('admin_userTrustedDevice_del')" ) + public R removeById(@RequestBody Long[] ids) { + return R.ok(userTrustedDeviceService.removeBatchByIds(CollUtil.toList(ids))); + } + + + /** + * 导出excel 表格 + * @param userTrustedDevice 查询条件 + * @param ids 导出指定ID + * @return excel 文件流 + */ + @ResponseExcel + @GetMapping("/export") + @PreAuthorize("@pms.hasPermission('admin_userTrustedDevice_export')" ) + public List export(UserTrustedDeviceEntity userTrustedDevice,Long[] ids) { + return userTrustedDeviceService.list(Wrappers.lambdaQuery(userTrustedDevice).in(ArrayUtil.isNotEmpty(ids), UserTrustedDeviceEntity::getId, ids)); + } +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/UserTrustedDeviceMapper.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/UserTrustedDeviceMapper.java new file mode 100644 index 000000000..53a3319e2 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/mapper/UserTrustedDeviceMapper.java @@ -0,0 +1,11 @@ +package com.bsd.pjcloud.admin.mapper; + +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import com.bsd.pjcloud.admin.api.entity.UserTrustedDeviceEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserTrustedDeviceMapper extends PjcloudBaseMapper { + + +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/UserTrustedDeviceService.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/UserTrustedDeviceService.java new file mode 100644 index 000000000..4f7610283 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/UserTrustedDeviceService.java @@ -0,0 +1,8 @@ +package com.bsd.pjcloud.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.admin.api.entity.UserTrustedDeviceEntity; + +public interface UserTrustedDeviceService extends IService { + +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/UserTrustedDeviceServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/UserTrustedDeviceServiceImpl.java new file mode 100644 index 000000000..5193e6f95 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/UserTrustedDeviceServiceImpl.java @@ -0,0 +1,16 @@ +package com.bsd.pjcloud.admin.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.admin.api.entity.UserTrustedDeviceEntity; +import com.bsd.pjcloud.admin.mapper.UserTrustedDeviceMapper; +import com.bsd.pjcloud.admin.service.UserTrustedDeviceService; +import org.springframework.stereotype.Service; +/** + * 设备指纹 + * + * @author zjf + * @date 2025-04-22 17:14:57 + */ +@Service +public class UserTrustedDeviceServiceImpl extends ServiceImpl implements UserTrustedDeviceService { +} \ No newline at end of file diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/UserTrustedDeviceMapper.xml b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/UserTrustedDeviceMapper.xml new file mode 100644 index 000000000..06b1459a5 --- /dev/null +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/mapper/UserTrustedDeviceMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file