diff --git a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/RemoteUserService.java b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/RemoteUserService.java index 3158f54..95fa005 100644 --- a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/RemoteUserService.java +++ b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/RemoteUserService.java @@ -53,6 +53,16 @@ public interface RemoteUserService { public R getUserInfoByPhone(@PathVariable("phone") String phone, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + /** + * 通过用户名查询用户信息 + * + * @param phone 手机号 + * @param source 请求来源 + * @return 结果 + */ + @GetMapping("/user/isWorkerPhone/{photoNumber}") + public boolean isWorkerPhone(@PathVariable("photoNumber") String photoNumber, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + /** * 通过用户名查询用户信息 * diff --git a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/factory/RemoteUserFallbackFactory.java b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/factory/RemoteUserFallbackFactory.java index 0694f32..c1bf3e8 100644 --- a/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/factory/RemoteUserFallbackFactory.java +++ b/bonus-api/bonus-api-system/src/main/java/com/bonus/system/api/factory/RemoteUserFallbackFactory.java @@ -19,7 +19,7 @@ import java.util.List; /** * 用户服务降级处理 - * + * * @author bonus */ @Component @@ -56,6 +56,11 @@ public class RemoteUserFallbackFactory implements FallbackFactory userResult = remoteUserService.getUserInfoByPhone(phone, SecurityConstants.INNER); + //验证用户是否存在 + passwordValidatorService.validateUserResult(phone, userResult); + LoginUser userInfo = userResult.getData(); + SysUser user = userInfo.getSysUser(); + passwordValidatorService.validateApprovalStatus(phone, user); + // 验证用户状态 + passwordValidatorService.validateUserStatus(phone, user); + + passwordValidatorService.processLoginBlackList(user); + //返回信息 + return userInfo; + } +} diff --git a/bonus-auth/src/main/java/com/bonus/auth/service/SysLoginService.java b/bonus-auth/src/main/java/com/bonus/auth/service/SysLoginService.java index bd1d8e5..d443961 100644 --- a/bonus-auth/src/main/java/com/bonus/auth/service/SysLoginService.java +++ b/bonus-auth/src/main/java/com/bonus/auth/service/SysLoginService.java @@ -10,7 +10,6 @@ import com.bonus.common.core.constant.UserConstants; import com.bonus.common.core.domain.R; import com.bonus.common.core.exception.ServiceException; import com.bonus.common.core.utils.StringUtils; -import com.bonus.common.core.utils.encryption.Sm4Utils; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.security.utils.SecurityUtils; import com.bonus.config.SystemConfig; @@ -55,6 +54,8 @@ public class SysLoginService { @Resource private RemoteConfigService configService; +// @Resource +// private RedisService redisService; /** * 获取验证码 * @@ -68,6 +69,13 @@ public class SysLoginService { if (strategyFactory == null) { return R.fail("不支持的方式"); } + //工人登录时加一个验证手机号 + if (verificationCodeType == VerificationCodeType.WORKER_LOGIN) { + boolean userResult = remoteUserService.isWorkerPhone(username, SecurityConstants.INNER); + if (!userResult) { + return R.fail("手机号不存在"); + } + } strategyFactory.sendVerificationCode(username); return R.ok(); } @@ -87,6 +95,53 @@ public class SysLoginService { } } +// /** +// * 下发短信 +// * @param phone +// * @return +// */ +// public AjaxResult sendPhone(String phone) { +// phone= Sm4Utils.decrypt(phone); +// //验证手机手机号是否存在 +// String thisUser=userService.getUserInfo(phone); +// if(!phone.equals(thisUser)){ +// AjaxResult ajax = AjaxResult.error(); +// ajax.put("msg", "手机号不存在或手机号不正确"); +// return ajax; +// } +// Integer num=redisService.getCacheObject(CacheConstants.PHONE_NUM+phone); +// if(num==null){ +// num=1; +// }else{ +// num++; +// } +// if(num>10){ +// return AjaxResult.error("请勿频繁发送验证码!"); +// } +// StringBuilder sb=new StringBuilder(); +//// String code = getSixBitCode(); +// String code = VerificationCodeUtils.generateVerificationCode(NUMERIC); +// sb.append("【博诺思】验证码:").append(code).append(",验证码有效期").append(CacheConstants.TIMES).append("分钟,切勿将验证码泄漏于他人。"); +// sb.append("发送时间:").append(DateUtils.getTime()); +// sb.append("。(实名制)"); +// Map map= PhoneUtils.sendPhoneMsg(phone,sb.toString()); +// if ("200".equals(map.get("code"))){ +// AjaxResult ajax = AjaxResult.success(); +// redisService.setCacheObject(CacheConstants.PHONE_CODE+phone,code,CacheConstants.TIMES, TimeUnit.MINUTES); +// redisService.setCacheObject(CacheConstants.PHONE_NUM+phone,num,5, TimeUnit.MINUTES); +// ajax.put("times", CacheConstants.TIMES); +// ajax.put("msg", "发送成功"); +// return ajax; +// }else{ +// AjaxResult ajax = AjaxResult.error(); +// ajax.put("times", CacheConstants.TIMES); +// ajax.put("msg", "发送失败,请检查网络!"); +// return ajax; +// } +// +// } + + /** * 用户注册 * diff --git a/bonus-auth/src/main/java/com/bonus/auth/service/WorkerLoginVerificationCodeSender.java b/bonus-auth/src/main/java/com/bonus/auth/service/WorkerLoginVerificationCodeSender.java new file mode 100644 index 0000000..81104a7 --- /dev/null +++ b/bonus-auth/src/main/java/com/bonus/auth/service/WorkerLoginVerificationCodeSender.java @@ -0,0 +1,95 @@ +package com.bonus.auth.service; + +import com.bonus.common.core.constant.SecurityConstants; +import com.bonus.common.core.domain.R; +import com.bonus.common.core.exception.ServiceException; +import com.bonus.common.security.service.EmailService; +import com.bonus.common.security.service.SmsService; +import com.bonus.system.api.RemoteUserService; +import com.bonus.system.api.model.LoginUser; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * 验证码发送服务 + * 可发送到邮箱或手机 + * + * @author bonus + */ +@Service +public class WorkerLoginVerificationCodeSender implements VerificationCodeStrategy { + + private static final String EMAIL_REGEX = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; + private static final String PHONE_REGEX = "^1[3-9]\\d{9}$"; + + @Resource + private EmailService emailService; + + @Resource + private SmsService smsService; + + @Resource + private RemoteUserService remoteUserService; + + /** + * 发送验证码到邮箱或手机 + * + * @param contactInfo 可以是邮箱地址或手机号码 + * @return 验证码发送的结果 + */ + @Override + public void sendVerificationCode(String contactInfo) { + if (isEmail(contactInfo)) { + emailService.sendSimpleEmail(contactInfo); + } else if (isPhone(contactInfo)) { + smsService.sendSimplePhone(contactInfo); + } else { + handleUsernameLogin(contactInfo); + } + } + + /** + * 检查是否是邮箱 + * + * @param contactInfo 输入信息 + * @return 是否为邮箱 + */ + private boolean isEmail(String contactInfo) { + return contactInfo.matches(EMAIL_REGEX); + } + + /** + * 检查是否是手机号 + * + * @param contactInfo 输入信息 + * @return 是否为手机号 + */ + private boolean isPhone(String contactInfo) { + return contactInfo.matches(PHONE_REGEX); + } + + /** + * 处理用户名登录逻辑 + * + * @param username 用户名 + * @return 验证码发送的结果 + */ + private void handleUsernameLogin(String username) { + R userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); + if (userResult == null || userResult.getData() == null || R.FAIL == userResult.getCode()) { + throw new ServiceException("用户名/密码错误"); + } + LoginUser user = userResult.getData(); + // 如果用户是管理员,则发送手机验证码 + if (user.getRoles().contains("admin")) { + if (StringUtils.isEmpty(user.getSysUser().getPhonenumber())) { + throw new ServiceException("此账号未绑定手机号,请先绑定手机号"); + } + smsService.sendSimplePhone(user.getSysUser().getPhonenumber()); + } else { + throw new ServiceException("不支持的登录方式"); + } + } +} diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/constant/CacheConstants.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/constant/CacheConstants.java index 65d39eb..0baedba 100644 --- a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/constant/CacheConstants.java +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/constant/CacheConstants.java @@ -67,4 +67,10 @@ public class CacheConstants { * 登录IP黑名单 cache key */ public static final String SYS_LOGIN_BLACKIPLIST ="blackIPList"; + + public static final String PHONE_CODE = "phone_code:"; + + public static final String PHONE_NUM = "phone_num:"; + + public static final Long TIMES = 5L; } diff --git a/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/PhoneUtils.java b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/PhoneUtils.java new file mode 100644 index 0000000..cf3c51f --- /dev/null +++ b/bonus-common/bonus-common-core/src/main/java/com/bonus/common/core/utils/PhoneUtils.java @@ -0,0 +1,101 @@ +package com.bonus.common.core.utils; + +import cn.hutool.http.HttpRequest; +import org.hibernate.validator.internal.util.StringHelper; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +/** + * 第三方依赖 + * + * cn.hutool + * hutool-all + * 5.8.22 + * + * 手机 短信 下发工具类 + * @author 黑子 + */ +public class PhoneUtils { + + /** + * 短信验证码 发送地址 及账号 + */ + public static String url="http://api.ktsms.cn/sms_token?ddtkey=bonus&secretkey=KtyBns@Admin2023!"; + + public static final String STRING_OK = "ok"; + /** + * 验证码时长 + * 分钟 + */ + public static final String TIMES = "5"; + + /** + * 系统平台名称 + */ + public static final String SYSTEM_NAME = "实名制"; + + /** + * 短信签名 + */ + public static final String PHONE_HEAD = "【博诺思】"; + + /** + * 发送短信验证吗 + * @param phone 手机号码 + * @param msg 消息内容 + * 如果msg不传 会使用默认值 + * @return + */ + public static Map sendPhoneMsg(String phone, String msg){ + Map map=new HashMap<>(4); + map.put("phone",phone); + if (!isValidPhoneNumber(phone)) { + map.put("code","201"); + map.put("msg","手机号格式错误,请输入11位数字号码"); + } + + StringBuilder sb=new StringBuilder(); + sb.append(url).append("&mobile=").append(phone); + sb.append("&content="); + if(StringHelper.isNullOrEmptyString(msg)){ + String code = getSixBitCode(); + map.put("captcha",code); + sb.append(PHONE_HEAD); + sb.append("您正在进行短信验证,验证码:").append(code).append(",请在").append(TIMES).append("分钟内完成验证,切勿将验证码泄漏于他人。"); + map.put("times",TIMES); + sb.append("发送时间:").append(DateUtils.getTime()).append("。("); + sb.append(SYSTEM_NAME).append(")"); + }else{ + sb.append(msg); + } + String body = HttpRequest.post(sb.toString()).execute(false).body(); + if (body == null || !body.contains(STRING_OK)) { + map.put("code","201"); + map.put("msg","短信发送失败"); + }else{ + ; map.put("code","200"); + map.put("msg","发送成功"); + } + + return map; + } + + + public static boolean isValidPhoneNumber(String phoneNumber) { + // 定义中国的手机号正则表达式 + String regex = "^1[3-9]\\d{9}$"; + return phoneNumber.matches(regex); + } + + + + private static String getSixBitCode() { + //随机数 + Random random = new Random(); + return String.valueOf(random.nextInt(900000) + 100000); + } + + +} diff --git a/bonus-gateway/src/main/java/com/bonus/gateway/filter/ValidateCodeFilter.java b/bonus-gateway/src/main/java/com/bonus/gateway/filter/ValidateCodeFilter.java index a572e0f..1df3f74 100644 --- a/bonus-gateway/src/main/java/com/bonus/gateway/filter/ValidateCodeFilter.java +++ b/bonus-gateway/src/main/java/com/bonus/gateway/filter/ValidateCodeFilter.java @@ -16,7 +16,6 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; -import java.nio.CharBuffer; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicReference; @@ -39,6 +38,10 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory { private static final String UUID = "uuid"; + private static final String WORKER_VERIFY = "verificationCodeType"; + + private static final String WORKER_LOGIN = "loginType"; + @Override public GatewayFilter apply(Object config) { return (exchange, chain) -> { @@ -59,8 +62,12 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory { throw new CaptchaException("请求参数异常"); } JSONObject obj = JSON.parseObject(rspStr); + //人员登录不要验证码,后面我会去验证手机号是否有效 + if ("WORKER_LOGIN".equals(obj.getString(WORKER_VERIFY)) || "PHONE_OTP_WORKER".equals(obj.getString(WORKER_LOGIN))) { + // 直接放行,不需要验证码验证 + return chain.filter(exchange); + } validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID)); - } catch (Exception e) { return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage()); } @@ -68,15 +75,30 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory { }; } +// private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { +// // 获取请求体 +// Flux body = serverHttpRequest.getBody(); +// AtomicReference bodyRef = new AtomicReference<>(); +// body.subscribe(buffer -> { +// CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); +// DataBufferUtils.release(buffer); +// bodyRef.set(charBuffer.toString()); +// }); +// return bodyRef.get(); +// } + private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { - // 获取请求体 Flux body = serverHttpRequest.getBody(); AtomicReference bodyRef = new AtomicReference<>(); + body.subscribe(buffer -> { - CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); + byte[] bytes = new byte[buffer.readableByteCount()]; + buffer.read(bytes); DataBufferUtils.release(buffer); - bodyRef.set(charBuffer.toString()); + bodyRef.set(new String(bytes, StandardCharsets.UTF_8)); }); + return bodyRef.get(); } + } diff --git a/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/AppRecognitionController.java b/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/AppRecognitionController.java index 8b7ef1a..0af827f 100644 --- a/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/AppRecognitionController.java +++ b/bonus-modules/bonus-bmw/src/main/java/com/bonus/bmw/controller/AppRecognitionController.java @@ -45,7 +45,6 @@ public class AppRecognitionController extends BaseController { /** * 人脸识别-识别人脸 */ - @RequiresPermissionsOrInnerAuth(innerAuth = @InnerAuth(isUser = false)) @PostMapping("/getFaceRecognition") @SysLog(title = "识别人脸", businessType = OperaType.QUERY, logType = 0, module = "识别服务接口->识别人脸", details = "识别人脸") diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java index 92a3d54..d0842ca 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/controller/SysUserController.java @@ -12,7 +12,6 @@ import com.bonus.common.log.annotation.SysLog; import com.bonus.common.log.enums.OperaType; import com.bonus.common.redis.service.RedisService; import com.bonus.common.security.annotation.InnerAuth; -import com.bonus.common.security.annotation.PreventRepeatSubmit; import com.bonus.common.security.annotation.RequiresPermissions; import com.bonus.common.security.annotation.RequiresPermissionsOrInnerAuth; import com.bonus.common.security.utils.SecurityUtils; @@ -23,7 +22,6 @@ import com.bonus.system.api.domain.SysUser; import com.bonus.system.api.model.LoginUser; import com.bonus.system.domain.UserPasswordHistory; import com.bonus.system.service.*; -import com.bonus.system.warning.WebSocketHandler; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -184,6 +182,16 @@ public class SysUserController extends BaseController { return R.ok(sysUserVo); } + /** + * 获取获取是否为施工人员 + */ + @InnerAuth + @GetMapping("/isWorkerPhone/{photoNumber}") + public boolean isWorkerPhone(@PathVariable("photoNumber") String photoNumber) { + int sysUserVo = userService.selectWorkerByPhotoNumber(photoNumber); + return sysUserVo > 0; + } + /** * 获取当前用户信息 */ diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java index 1e2a865..067cb0c 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/mapper/SysUserMapper.java @@ -167,4 +167,6 @@ public interface SysUserMapper { * @date 2025/8/18 16:15 */ Long getAffCompany(SysUser user); + + int selectWorkerByPhotoNumber(String photoNumber); } diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java index 612deb2..2b4f7ec 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/ISysUserService.java @@ -5,7 +5,6 @@ import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.system.api.domain.SysRole; import com.bonus.system.api.domain.SysUser; import org.apache.poi.ss.formula.functions.T; -import org.aspectj.weaver.loadtime.Aj; import java.util.List; @@ -239,4 +238,12 @@ public interface ISysUserService { public AjaxResult systemUpdateUser(SysUser user); AjaxResult getRoleList(SysRole role); + + /** + * 根据手机号查询用户 + * + * @param photoNumber 手机号 + * @return 用户对象信息 + */ + int selectWorkerByPhotoNumber(String photoNumber); } diff --git a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java index 1a7f6f7..7f6c15f 100644 --- a/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java +++ b/bonus-modules/bonus-system/src/main/java/com/bonus/system/service/impl/SysUserServiceImpl.java @@ -1,6 +1,5 @@ package com.bonus.system.service.impl; -import com.bonus.common.core.constant.Constants; import com.bonus.common.core.constant.UserConstants; import com.bonus.common.core.domain.R; import com.bonus.common.core.exception.ServiceException; @@ -11,7 +10,6 @@ import com.bonus.common.core.utils.encryption.Sm4Utils; import com.bonus.common.core.utils.sms.SmsUtils; import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.core.web.domain.BaseEntity; -import com.bonus.common.core.web.domain.TreeEntity; import com.bonus.common.datascope.annotation.DataScope; import com.bonus.common.datascope.utils.CommonDataPermissionInfo; import com.bonus.common.security.config.VerificationCodeConfig; @@ -21,13 +19,11 @@ import com.bonus.system.api.domain.SysRole; import com.bonus.system.api.domain.SysUser; import com.bonus.system.api.domain.SysUserRole; import com.bonus.system.domain.SysUserPost; -import com.bonus.system.domain.vo.TreeSelect; import com.bonus.system.mapper.*; import com.bonus.system.service.ISysConfigService; import com.bonus.system.service.ISysDeptService; import com.bonus.system.service.ISysUserService; import org.apache.poi.ss.formula.functions.T; -import org.checkerframework.checker.units.qual.A; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; @@ -42,7 +38,6 @@ import javax.annotation.Resource; import javax.validation.Validator; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -702,4 +697,9 @@ public class SysUserServiceImpl implements ISysUserService { return AjaxResult.error(); } } + + @Override + public int selectWorkerByPhotoNumber(String photoNumber) { + return userMapper.selectWorkerByPhotoNumber(photoNumber); + } } diff --git a/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml b/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml index 543c4d4..7787b7b 100644 --- a/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/bonus-modules/bonus-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -437,5 +437,9 @@ - +