diff --git a/bonus-auth/src/main/java/com/bonus/auth/controller/TokenController.java b/bonus-auth/src/main/java/com/bonus/auth/controller/TokenController.java index 2192d51..1839a7f 100644 --- a/bonus-auth/src/main/java/com/bonus/auth/controller/TokenController.java +++ b/bonus-auth/src/main/java/com/bonus/auth/controller/TokenController.java @@ -41,7 +41,6 @@ public class TokenController { */ @PostMapping("login") public R login(@RequestBody LoginBody form) { - LoginUser userInfo; if ("mobile".equals(form.getLoginType())) { userInfo = sysLoginService.login(form.getMobile(), form.getPassword(), form.getLoginType()); @@ -59,7 +58,7 @@ public class TokenController { */ @PostMapping("getPhoneCode") public R getPhoneCode(@RequestBody LoginBody form) { - return sysLoginService.getPhoneCode(form.getMobile(), form.getLoginType()); + return sysLoginService.getPhoneCode(form.getMobile(), form.getMobileCodeType()); } /** diff --git a/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java b/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java index 1069ec3..5448000 100644 --- a/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java +++ b/bonus-auth/src/main/java/com/bonus/auth/form/LoginBody.java @@ -29,6 +29,16 @@ public class LoginBody { private String loginType; + private String mobileCodeType; + + public String getMobileCodeType() { + return mobileCodeType; + } + + public void setMobileCodeType(String mobileCodeType) { + this.mobileCodeType = mobileCodeType; + } + public String getMobile() { return mobile; } 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 6aabb9b..d3d9987 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 @@ -3,6 +3,7 @@ package com.bonus.auth.service; import com.bonus.auth.form.RegisterBody; import com.bonus.common.core.constant.*; import com.hankcs.hanlp.HanLP; +import org.apache.poi.ss.formula.functions.T; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -52,11 +53,11 @@ public class SysLoginService { /** * 获取验证码 * - * @param username 用户名或手机号 - * @param loginType 登录类型(register:注册,其他:登录) + * @param username 用户名或手机号 + * @param getMobileCodeType 获取验证码类型(register:注册,其他:登录) * @return 响应结果 */ - public R getPhoneCode(String username, String loginType) { + public R getPhoneCode(String username, String getMobileCodeType) { long startTime = System.currentTimeMillis(); // 记录开始时间 int contactType = getContactType(username); if (contactType == 2) { @@ -65,8 +66,7 @@ public class SysLoginService { } R userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); boolean userExists = userResult != null && userResult.getData() != null; - - if ("register".equals(loginType)) { + if ("register".equals(getMobileCodeType)) { handleRegister(username, startTime, contactType, userExists); } else { handleLogin(username, startTime, contactType, userExists); @@ -145,35 +145,22 @@ public class SysLoginService { * @return 登录用户信息 */ public LoginUser login(String username, String password, String loginType) { - long startTime = System.currentTimeMillis(); // 记录开始时间 - - if ("mobile".equals(loginType)) { - int contactType = getContactType(username); - if (contactType == 0) { - if (!supportsEmailLogin) { - recordLogService.saveLogs(username, startTime, "邮箱登录不支持", "邮箱登录未开启", null, "失败"); - throw new ServiceException("邮箱登录未开启"); - } - } else if (contactType == 1) { - if (!supportsPhoneLogin) { - recordLogService.saveLogs(username, startTime, "手机登录不支持", "手机登录未开启", null, "失败"); - throw new ServiceException("手机登录未开启"); - } + long startTime = System.currentTimeMillis(); + int contactType = getContactType(username); + if (contactType == 0) { + if (!supportsEmailLogin) { + recordLogService.saveLogs(username, startTime, "邮箱登录不支持", "邮箱登录未开启", null, "失败"); + throw new ServiceException("用户名/密码错误"); } + } else if (contactType == 1) { + if (!supportsPhoneLogin) { + recordLogService.saveLogs(username, startTime, "手机登录不支持", "手机登录未开启", null, "失败"); + throw new ServiceException("用户名/密码错误"); + } + }// 记录开始时间 + if ("mobile".equals(loginType)) { return handleMobileLogin(username, startTime); } else { - int contactType = getContactType(username); - if (contactType == 0) { - if (!supportsEmailLogin) { - recordLogService.saveLogs(username, startTime, "邮箱登录不支持", "邮箱登录未开启", null, "失败"); - throw new ServiceException("邮箱登录未开启"); - } - } else if (contactType == 1) { - if (!supportsPhoneLogin) { - recordLogService.saveLogs(username, startTime, "手机登录不支持", "手机登录未开启", null, "失败"); - throw new ServiceException("手机登录未开启"); - } - } return handleUsernamePasswordLogin(username, password, startTime); } @@ -192,7 +179,7 @@ public class SysLoginService { LoginUser userInfo = userResult.getData(); SysUser user = userInfo.getSysUser(); - + validateApprovalStatus(user.getUserName(), user, startTime); validateIpBlacklist(user.getUserName(), startTime); validateUserStatus(user.getUserName(), user, startTime); @@ -211,16 +198,14 @@ public class SysLoginService { private LoginUser handleUsernamePasswordLogin(String username, String password, long startTime) { validateLoginParameters(username, password, startTime); // 验证登录参数 validateIpBlacklist(username, startTime); // IP黑名单校验 - R userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER); validateUserResult(username, userResult, startTime); // 验证用户查询结果 - LoginUser userInfo = userResult.getData(); SysUser user = userInfo.getSysUser(); + validateApprovalStatus(username, user, startTime); validateUserStatus(username, user, startTime); // 验证用户状态 passwordService.validate(user, password, startTime); // 验证密码 handleIpValidation(username, user, startTime); // 处理IP校验 - recordLogService.saveLogs(username, startTime, "登陆成功", "用户名密码登录成功", user.getUserId().toString(), "成功"); return userInfo; } @@ -240,12 +225,12 @@ public class SysLoginService { if (password.length() < ValidateUtils.MIN_LENGTH || password.length() > ValidateUtils.MAX_LENGTH) { recordLogService.saveLogs(username, startTime, "密码格式不正确", "密码格式不正确", null, "失败"); - throw new ServiceException("密码格式不正确"); + throw new ServiceException("用户名/密码错误"); } if (username.length() < UserConstants.USERNAME_MIN_LENGTH || username.length() > UserConstants.USERNAME_MAX_LENGTH) { recordLogService.saveLogs(username, startTime, "用户名格式不正确", "用户名格式不正确", null, "失败"); - throw new ServiceException("用户名格式不正确"); + throw new ServiceException("用户名/密码错误"); } } @@ -282,6 +267,14 @@ public class SysLoginService { } } + + private void validateApprovalStatus(String username, SysUser user, long startTime) { + if ("0".equals(user.getApprovalStatus())) { + recordLogService.saveLogs(username, startTime, "账号未审批", "用户不存在", null, "失败"); + throw new ServiceException("账号未审批,请联系管理员"); + } + } + /** * 验证用户状态 * @@ -311,7 +304,6 @@ public class SysLoginService { if (!nowIp.equals(hisIp)) { recordLogService.saveErrorLogs(username, startTime, user.getUserId().toString()); } - redisService.setCacheObject("IP:" + user.getUserId().toString(), nowIp, 5L, TimeUnit.MINUTES); } catch (Exception e) { recordLogService.saveLogs(username, startTime, "IP校验异常", e.getMessage(), null, "失败"); @@ -357,6 +349,7 @@ public class SysLoginService { sysUser.setUserName(registerBody.getUsername()); sysUser.setNickName(registerBody.getNickName()); sysUser.setStatus("1"); + sysUser.setApprovalStatus("0"); //有要求另加 sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword())); diff --git a/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java b/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java index 837cd39..8a54609 100644 --- a/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java +++ b/bonus-gateway/src/main/java/com/bonus/gateway/filter/AecDecryptParamFilter.java @@ -19,6 +19,7 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriComponentsBuilder; import reactor.core.publisher.Flux; @@ -49,26 +50,12 @@ public class AecDecryptParamFilter extends AbstractGatewayFilterFactory { log.info("解密功能已禁用,直接继续过滤链。"); return chain.filter(exchange); } - ServerHttpRequest request = exchange.getRequest(); - HttpMethod method = request.getMethod(); - if (method == null) { - log.error("请求方法为 null,无法处理请求。"); - return chain.filter(exchange); - } - - try { - if (method == HttpMethod.GET) { - return handleGetRequest(exchange, chain); - } - if (method == HttpMethod.DELETE) { - return chain.filter(exchange); - } - return handleRequest(exchange, chain); - } catch (Exception e) { - log.error("处理请求时发生错误: {}", e.getMessage(), e); - exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); - return exchange.getResponse().setComplete(); + boolean hasContentHeader = request.getHeaders().containsKey("Content-Type"); + if (hasContentHeader) { + return handlePostPutRequest(exchange, chain); + } else { + return handleGetRequest(exchange, chain); } }; } @@ -88,7 +75,7 @@ public class AecDecryptParamFilter extends AbstractGatewayFilterFactory { } } - private Mono handleRequest(ServerWebExchange exchange, GatewayFilterChain chain) { + private Mono handlePostPutRequest(ServerWebExchange exchange, GatewayFilterChain chain) { return DataBufferUtils.join(exchange.getRequest().getBody()) .flatMap(dataBuffer -> { byte[] body = new byte[dataBuffer.readableByteCount()]; @@ -178,7 +165,7 @@ public class AecDecryptParamFilter extends AbstractGatewayFilterFactory { * 数据完整性校验 * * @param providedHmac 请求头中的 HMAC 值 - * @param query 请求参数 + * @param query 请求参数 */ private void integrityVerification(String providedHmac, String query) { if (providedHmac == null) { diff --git a/bonus-gateway/src/main/java/com/bonus/gateway/filter/ResponseEncryptFilter.java b/bonus-gateway/src/main/java/com/bonus/gateway/filter/ResponseEncryptFilter.java index ff36bf9..be0a0a1 100644 --- a/bonus-gateway/src/main/java/com/bonus/gateway/filter/ResponseEncryptFilter.java +++ b/bonus-gateway/src/main/java/com/bonus/gateway/filter/ResponseEncryptFilter.java @@ -34,6 +34,7 @@ import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; /** * 对返回的 data数据进行加密 + * * @author 黑子 */ @Configuration @@ -41,11 +42,11 @@ import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; public class ResponseEncryptFilter implements GlobalFilter, Ordered { @Value("${system.encryptEnabled}") - public boolean encryptEnabled; + public boolean encryptEnabled; /** * 返回的数据 是否加密 */ - public final static String KEY_HEAD="decrypt"; + public final static String KEY_HEAD = "decrypt"; @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { @@ -54,30 +55,30 @@ public class ResponseEncryptFilter implements GlobalFilter, Ordered { ServerHttpRequest request = exchange.getRequest(); URI uri = request.getURI(); - HttpHeaders headers=request.getHeaders(); - if(headers!=null){ - Object object=headers.getFirst("Content-Type"); - Object head=headers.getFirst(SystemGlobal.KEY_ENCRYPT); - if (head!=null){ - String keyHead=head.toString(); - if (SystemGlobal.KEY_ENCRYPT.equals(keyHead)){ + HttpHeaders headers = request.getHeaders(); + if (headers != null) { + Object object = headers.getFirst("Content-Type"); + Object head = headers.getFirst(SystemGlobal.KEY_ENCRYPT); + if (head != null) { + String keyHead = head.toString(); + if (SystemGlobal.KEY_ENCRYPT.equals(keyHead)) { return chain.filter(exchange); } } - if(object!=null){ - String contentType=object.toString(); - if (contentType.contains(MULTIPART_FORM_DATA_VALUE)){ + if (object != null) { + String contentType = object.toString(); + if (contentType.contains(MULTIPART_FORM_DATA_VALUE)) { return chain.filter(exchange); } } } HttpStatus statusCode = exchange.getResponse().getStatusCode(); - if(Objects.equals(statusCode, HttpStatus.BAD_REQUEST) || Objects.equals(statusCode, HttpStatus.TOO_MANY_REQUESTS)){ + if (Objects.equals(statusCode, HttpStatus.BAD_REQUEST) || Objects.equals(statusCode, HttpStatus.TOO_MANY_REQUESTS)) { // 如果是特殊的请求,已处理响应内容,这里不再处理 return chain.filter(exchange); } //是否加密 - if(!encryptEnabled){ + if (!encryptEnabled) { return chain.filter(exchange); } // 根据具体业务内容,修改响应体 @@ -86,11 +87,12 @@ public class ResponseEncryptFilter implements GlobalFilter, Ordered { /** * 修改响应体 + * * @param exchange * @param chain * @return */ - private Mono modifyResponseBody(ServerWebExchange exchange, GatewayFilterChain chain) { + private Mono modifyResponseBody(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpResponse originalResponse = exchange.getResponse(); originalResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON); DataBufferFactory bufferFactory = originalResponse.bufferFactory(); @@ -103,6 +105,7 @@ public class ResponseEncryptFilter implements GlobalFilter, Ordered { public int getOrder() { return -5; } + @SuppressWarnings("deprecation") private ServerHttpResponseDecorator buildResponse(ServerHttpResponse originalResponse, DataBufferFactory bufferFactory) { return new ServerHttpResponseDecorator(originalResponse) { @@ -121,22 +124,22 @@ public class ResponseEncryptFilter implements GlobalFilter, Ordered { System.out.println(responseData); Map map = JSON.parseObject(responseData); Object encrypt = map.get(SystemGlobal.KEY_DECRYPT); - Map maps= Maps.newHashMap(); - if(encrypt==null || encrypt=="" || SystemGlobal.TRUE_STR.equals(encrypt)){ - responseData = AesCbcUtils.encrypt(JSON.toJSONString(map)); - maps.put("data",responseData); - maps.put(SystemGlobal.KEY_DECRYPT,true); - responseData=JSON.toJSONString(maps); - }else{ - maps.put("data",responseData); - maps.put(SystemGlobal.KEY_DECRYPT,false); + Map maps = Maps.newHashMap(); + if (encrypt == null || encrypt == "" || SystemGlobal.TRUE_STR.equals(encrypt)) { + responseData = AesCbcUtils.encrypt(JSON.toJSONString(map)); + maps.put("data", responseData); + maps.put(SystemGlobal.KEY_DECRYPT, true); + responseData = JSON.toJSONString(maps); + } else { + maps.put("data", responseData); + maps.put(SystemGlobal.KEY_DECRYPT, false); } byte[] uppedContent = responseData.getBytes(Charsets.UTF_8); originalResponse.getHeaders().setContentLength(uppedContent.length); return bufferFactory.wrap(uppedContent); })); } else { - log.error("获取响应体数据 :"+getStatusCode()); + log.error("获取响应体数据 :" + getStatusCode()); } return super.writeWith(body); } 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 ba9d66a..1732ab9 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 @@ -66,7 +66,7 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory { throw new CaptchaException("请求参数异常"); } JSONObject obj = JSON.parseObject(rspStr); - if (ObjectUtils.isNotEmpty(obj.getString("loginType")) && StringUtils.equals(obj.getString("loginType"), "mobile")) { + if (ObjectUtils.isNotEmpty(obj) && ObjectUtils.isNotEmpty(obj.getString("loginType")) && StringUtils.equals(obj.getString("loginType"), "mobile")) { validateCodeService.checkPhoneCaptcha(obj.getString("verificationCode"), obj.getString("mobile")); } else { validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID)); diff --git a/bonus-modules/bonus-system/pom.xml b/bonus-modules/bonus-system/pom.xml index ae623e5..3e093e4 100644 --- a/bonus-modules/bonus-system/pom.xml +++ b/bonus-modules/bonus-system/pom.xml @@ -84,6 +84,11 @@ compile + + org.springframework.boot + spring-boot-starter-mail + + 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 042078c..d2a1ad4 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 @@ -2,15 +2,24 @@ package com.bonus.system.service.impl; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import javax.annotation.Resource; import javax.validation.Validator; +import com.bonus.common.core.constant.CacheConstants; +import com.bonus.common.core.constant.Constants; import com.bonus.common.core.domain.R; +import com.bonus.common.core.utils.VerificationCodeUtils; +import com.bonus.common.core.utils.sms.SmsUtils; +import com.bonus.common.redis.service.RedisService; import org.apache.poi.ss.formula.functions.T; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -73,6 +82,10 @@ public class SysUserServiceImpl implements ISysUserService { @Autowired protected Validator validator; + + @Autowired + private JavaMailSender mailSender; // 自动注入JavaMailSender,用于发送邮件 + /** * 根据条件分页查询用户列表 * @@ -528,8 +541,18 @@ public class SysUserServiceImpl implements ISysUserService { @Override public R approvalStatus(Long userId) { try { + SysUser sysUser = userMapper.selectUserById(userId); + if ("1".equals(sysUser.getApprovalStatus())) { + return R.fail("该用户已通过审批"); + } Integer i = userMapper.approvalStatus(userId); if (i > 0) { + if (StringUtils.isNotEmpty(sysUser.getPhonenumber())) { + SmsUtils.smsToken(sysUser.getPhonenumber(), "您的账号:" + sysUser.getUserName() + "已通过审批,请登录系统", ""); + } + if (StringUtils.isNotEmpty(sysUser.getEmail())) { + sendSimpleEmail(sysUser.getEmail(), "您的账号:" + sysUser.getUserName() + "已通过审批,请登录系统"); + } return R.ok(); } else { return R.fail(); @@ -540,4 +563,20 @@ public class SysUserServiceImpl implements ISysUserService { } } + /** + * 发送简单邮件 + * + * @param to 接收者邮箱地址 + */ + public R sendSimpleEmail(String to, String content) { + // 创建一个简单邮件消息对象 + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom("2642480752@qq.com"); // 发件人邮箱地址 + message.setTo(to); // 收件人邮箱地址 + message.setSubject("【博诺思】"); // 邮件主题 + message.setText(content); // 邮件内容 + mailSender.send(message); // 发送邮件 + return R.ok(); + } + } 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 97a0ee7..b297fe2 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 @@ -66,6 +66,7 @@ u.create_by, u.create_time, u.remark, + u.approval_status, d.dept_id, d.parent_id, d.ancestors, @@ -212,6 +213,7 @@ create_by, remark, login_type, + approval_status, create_time )values( #{userId}, @@ -227,6 +229,7 @@ #{createBy}, #{remark}, #{loginType}, + #{approvalStatus}, sysdate() )