diff --git a/kn-common/src/main/java/org/springblade/common/cache/CacheNames.java b/kn-common/src/main/java/org/springblade/common/cache/CacheNames.java index eecea67..f9c2d6c 100644 --- a/kn-common/src/main/java/org/springblade/common/cache/CacheNames.java +++ b/kn-common/src/main/java/org/springblade/common/cache/CacheNames.java @@ -62,4 +62,9 @@ public interface CacheNames { */ String USER_FAIL_KEY = "blade:user::blade:fail:"; + /** + * 邮箱修改密码验证码key + */ + String EMAIL_FORGET_KEY = "blade:auth::blade:email:forget:"; + } diff --git a/kn-common/src/main/java/org/springblade/common/constant/CommonConstant.java b/kn-common/src/main/java/org/springblade/common/constant/CommonConstant.java index 9d43d7b..fb9e595 100644 --- a/kn-common/src/main/java/org/springblade/common/constant/CommonConstant.java +++ b/kn-common/src/main/java/org/springblade/common/constant/CommonConstant.java @@ -26,7 +26,6 @@ public interface CommonConstant { * 默认密码 */ String DEFAULT_PASSWORD = "123456"; - /** * 默认密码参数值 */ diff --git a/kn-service-api/biz-vordm-api/src/main/java/com/kening/vordm/entity/DisasterInfo.java b/kn-service-api/biz-vordm-api/src/main/java/com/kening/vordm/entity/DisasterInfo.java index bf7da7c..c77da9e 100644 --- a/kn-service-api/biz-vordm-api/src/main/java/com/kening/vordm/entity/DisasterInfo.java +++ b/kn-service-api/biz-vordm-api/src/main/java/com/kening/vordm/entity/DisasterInfo.java @@ -169,5 +169,17 @@ public class DisasterInfo implements Serializable { */ @TableField(exist = false) private String allocation; + /** + * 拒绝标题 + */ + @TableField(exist = false) + private String refuseTitle; + /** + * 拒绝理由 + */ + @TableField(exist = false) + private String refuseReason; + + } diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/VoRdmApplication.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/VoRdmApplication.java index cd32db5..6097f7d 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/VoRdmApplication.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/VoRdmApplication.java @@ -11,6 +11,6 @@ import org.springframework.cloud.client.SpringCloudApplication; @SpringCloudApplication public class VoRdmApplication { public static void main(String[] args) { - BladeApplication.run(CommonConstant.KN_VORDM_MODULE_NAME, VoRdmApplication.class, args); + BladeApplication.run("yyhouc-"+CommonConstant.KN_VORDM_MODULE_NAME, VoRdmApplication.class, args); } } diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/AdministratorController.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/AdministratorController.java index ef7402b..890f803 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/AdministratorController.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/AdministratorController.java @@ -1,19 +1,24 @@ package com.kening.vordm.controller; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.kening.vordm.entity.Administrator; import com.kening.vordm.service.AdministratorService; import lombok.AllArgsConstructor; +import org.springblade.core.cache.utils.CacheUtil; import org.springblade.core.mp.support.Condition; import org.springblade.core.mp.support.Query; import org.springblade.core.secure.BladeUser; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.DigestUtil; import org.springblade.core.tool.utils.Func; +import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import java.util.Map; +import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE; + /** * 后台管理系统-chief管理员管理控制器 * @author liyuchen @@ -47,6 +52,7 @@ public class AdministratorController { */ @PostMapping("/add") public R add(@RequestBody Administrator administrator){ + CacheUtil.clear(USER_CACHE); return R.status(service.saveChiefAdmin(administrator)); } @@ -57,6 +63,7 @@ public class AdministratorController { */ @PutMapping("/update") public R update(@RequestBody Administrator administrator){ + CacheUtil.clear(USER_CACHE); return R.status(service.updateById(administrator)); } @@ -69,4 +76,53 @@ public class AdministratorController { public R delete(@RequestParam String ids){ return R.status(service.deleteLogic(Func.toLongList(ids))); } + /** + * 重置密码前发送邮件验证码 + */ + @GetMapping("/sendEmailCode") + public R sendEmailCode(@RequestParam String email,@RequestParam String tenantId){ + return R.data(service.sendEmailCode(email,tenantId)); + } + /** + * 验证账号或邮箱是否存在 + */ + @GetMapping("/checkAccountOrEmail") + public R checkAccountOrEmail(@RequestParam String email,@RequestParam String tenantId ){ + return R.data(service.checkAccountOrEmail(email,tenantId)); + } + /** + * 修改密码 + */ + @PutMapping("/updatePassword") + public R updatePassword(@RequestParam String email,@RequestParam String newPassword,@RequestParam String tenantId,@RequestParam String code){ + CacheUtil.clear(USER_CACHE); + return R.data(service.updatePassword(email,newPassword,tenantId,code)); + } + /** + * 根据账号验证传入的密码是否正确 + */ + @GetMapping("/checkPassword") + public R checkPassword(@RequestParam String account,@RequestParam String tenantId,@RequestParam String password){ + Administrator administrator = service.getOne(Wrappers.query().lambda().eq(Administrator::getAccount,account).eq(Administrator::getTenantId,tenantId)); + if(administrator == null){ + return R.data(false); + } + return R.data(administrator.getPassword().equals(DigestUtil.encrypt(password))); + } + /** + * 根据老密码修改密码 + */ + @PutMapping("/updatePasswordByOldPassword") + public R updatePasswordByOldPassword(@RequestParam String account,@RequestParam String tenantId,@RequestParam String oldPassword,@RequestParam String newPassword){ + CacheUtil.clear(USER_CACHE); + Administrator administrator = service.getOne(Wrappers.query().lambda().eq(Administrator::getAccount,account).eq(Administrator::getTenantId,tenantId)); + if(administrator == null){ + return R.data(false); + } + if(administrator.getPassword().equals(DigestUtil.encrypt(oldPassword))){ + administrator.setPassword(DigestUtil.encrypt(newPassword)); + return R.data(service.updateById(administrator)); + } + return R.data(false); + } } diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/CrawlInfoController.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/CrawlInfoController.java index 4dab821..487a988 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/CrawlInfoController.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/CrawlInfoController.java @@ -1,5 +1,7 @@ package com.kening.vordm.controller; +import cn.hutool.crypto.digest.MD5; +import com.alibaba.nacos.common.utils.MD5Utils; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; @@ -15,6 +17,8 @@ import org.springblade.core.mp.support.Query; import org.springblade.core.tool.api.R; import org.springframework.web.bind.annotation.*; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; @@ -99,5 +103,30 @@ public class CrawlInfoController { List list = crawlInfoService.list(Wrappers.query().lambda().eq(CrawlInfo::getDisasterId, disasterId).notIn(CrawlInfo::getType, "1","2","3","4")); return R.data(list); } + + public static void main(String[] args) { + String key = encrypt("^RUWY6@d&%hVf5qYY9basW21KIaBmuER"); + long time = System.currentTimeMillis()/1000; + System.out.println(time+"-"+encrypt((key+time))); + } + public static String encrypt(String plaintext) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(plaintext.getBytes()); + byte[] bytes = md.digest(); + StringBuilder result = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(b & 0xff); + if (hex.length() == 1) { + result.append("0"); + } + result.append(hex); + } + return result.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; + } } diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/DisasterInfoController.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/DisasterInfoController.java index 40520a9..933f9c2 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/DisasterInfoController.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/controller/DisasterInfoController.java @@ -2,6 +2,7 @@ package com.kening.vordm.controller; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.StringUtils; @@ -337,14 +338,32 @@ public class DisasterInfoController { private final AdministratorService administratorService; @PostMapping("review") public R review(@RequestBody DisasterInfo disasterInfo) { + //审核邮件实例化 + Email email = new Email(); + //查询邮箱 + QueryWrapper qw = new QueryWrapper<>(); + qw.apply("id = (select sponsor_id from guest_manage_disaster_ref where disaster_id = {0})", disasterInfo.getId()); + GuestInfo guestInfo = guestInfoService.getOne(qw); + email.setTos(new String[]{ guestInfo.getEmail()}); //审批通过 响应状态,0未审批,1审批未通过。2审批通过并正在响应,3审批通过并且响应完成 if (disasterInfo.getRespondStatus() == 2) { String numbering = serialNumberService.generateNumbering(disasterInfo.getDisasterType()); disasterInfo.setVordmId(numbering); disasterInfo.setRespondTime(new Date()); + email.setSubject("Your disaster response application has been approved!"); + email.setText("Your disaster response application has been approved!"); + }else{ + email.setSubject(disasterInfo.getRefuseTitle()); + email.setText(disasterInfo.getRefuseReason()); } - Boolean flag = disasterInfoService.updateById(disasterInfo); - return R.data(flag); +// Boolean flag = disasterInfoService.updateById(disasterInfo); + //保证数据在更新完后发送邮件。防止数据更新失败,邮件发送成功 + try { + emailService.sendMimeMessage(email); + } catch (Exception e) { + return R.fail("发送失败"); + } + return R.data(true); } private final EmailService emailService; diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/AdministratorService.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/AdministratorService.java index a3d3ba0..d25ecd8 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/AdministratorService.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/AdministratorService.java @@ -23,4 +23,10 @@ public interface AdministratorService extends BaseService { * @return */ boolean saveChiefAdmin(Administrator administrator); + + boolean sendEmailCode(String email,String tenantId); + + boolean checkAccountOrEmail(String email ,String tenantId); + + boolean updatePassword(String email, String newPassword, String tenantId, String code); } diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/EmailService.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/EmailService.java index 2761b64..55ee220 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/EmailService.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/EmailService.java @@ -16,6 +16,7 @@ public interface EmailService { void sendMimeMessage(Email email) throws MessagingException; void sendTemplate(Email email) throws MessagingException; + void sendTemplate(Email email,String template) throws MessagingException; R sendUserPasswordEmail(UserVo userVo) throws MessagingException; } diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/AdministratorServiceImpl.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/AdministratorServiceImpl.java index 6d46375..fe645bd 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/AdministratorServiceImpl.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/AdministratorServiceImpl.java @@ -1,20 +1,22 @@ package com.kening.vordm.service.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.kening.vordm.entity.Administrator; import com.kening.vordm.entity.Email; import com.kening.vordm.mapper.AdministratorMapper; import com.kening.vordm.service.AdministratorService; import com.kening.vordm.service.EmailService; -import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springblade.common.cache.CacheNames; import org.springblade.core.mp.base.BaseServiceImpl; +import org.springblade.core.redis.cache.BladeRedis; import org.springblade.core.tool.utils.DigestUtil; +import org.springblade.core.tool.utils.StringUtil; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import java.time.Duration; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.HashMap; @@ -32,6 +34,8 @@ public class AdministratorServiceImpl extends BaseServiceImpllambdaQuery().eq(Administrator::getEmail,email).eq(Administrator::getTenantId,tenantId)); + if(admin==null){ + throw new RuntimeException("The email is not registered"); + } + + //随机生成6位数验证码 + String code = String.valueOf((int)((Math.random()*9+1)*100000)); + //将验证码存入redis ,有效期10分钟 + Duration duration = Duration.ofMinutes(10); + bladeRedis.setEx(CacheNames.EMAIL_FORGET_KEY +email,code,duration); + try { + //设置标题 + String subject = "Verification code"; + //设置要填充模板的参数 + Map dataMap = new HashMap<>(); + dataMap.put("code", code); + dataMap.put("account",admin.getAccount()); + dataMap.put("email",admin.getEmail()); + Email emailObj = new Email(); + emailObj.setSubject(subject); + emailObj.setHtmlText(true); + emailObj.setTos(new String[]{email}); + emailObj.setDataMap(dataMap); + emailService.sendTemplate(emailObj, "forgotPassword"); + log.info("邮件发送成功"); + return true; + }catch (Exception e){ + log.error("发送邮件失败:{}",e); + } + return false; + } + + @Override + public boolean checkAccountOrEmail(String email,String tenantId) { + //查询用户是否存在 + Administrator admin = getOne(Wrappers.lambdaQuery().eq(Administrator::getEmail,email).eq(Administrator::getTenantId,tenantId)); + return admin!=null; + } + + @Override + public boolean updatePassword(String email, String newPassword, String tenantId, String code) { + //首先根据邮箱、租户id查询用户是否存在 + Administrator admin = getOne(Wrappers.lambdaQuery().eq(Administrator::getEmail,email).eq(Administrator::getTenantId,tenantId)); + if(admin==null){ + throw new RuntimeException("The email is not registered"); + } + //判断验证码是否为空 + if(StringUtil.isBlank(code)){ + throw new RuntimeException("Verification code cannot be empty"); + } + //校验验证码是否正确 + String codeRedis = bladeRedis.get(CacheNames.EMAIL_FORGET_KEY + email); + //如果codeRedis 验证码为空返回请发送验证码提示 + if(StringUtil.isBlank(codeRedis)){ + throw new RuntimeException("Please send the verification code first"); + } + //将redis中的验证码设置为-100,并且超时时间为50秒 + bladeRedis.setEx(CacheNames.EMAIL_FORGET_KEY + email,"-100",Duration.ofSeconds(50)); + //判断当前验证码是否为-100,如果是-100则提示验证码已过期 + if("-100".equals(codeRedis)){ + throw new RuntimeException("Verification code has expired"); + } + if(!code.equals(codeRedis)){ + throw new RuntimeException("Verification code error"); + } + //修改密码 + admin.setPassword(DigestUtil.encrypt(newPassword)); + if(updateById(admin)){ + //删除redis中的验证码 + bladeRedis.del(CacheNames.EMAIL_FORGET_KEY + email); + return true; + } + return false ; + } + } diff --git a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/EmailServiceImpl.java b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/EmailServiceImpl.java index 5f76752..477af04 100644 --- a/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/EmailServiceImpl.java +++ b/kn-service/biz-vordm/src/main/java/com/kening/vordm/service/impl/EmailServiceImpl.java @@ -52,6 +52,11 @@ public class EmailServiceImpl implements EmailService { javaMailSender.send(buildTemplateMail(email)); } + @Override + public void sendTemplate(Email email, String template) throws MessagingException { + javaMailSender.send(buildTemplateMail(email,template)); + } + @Override public R sendUserPasswordEmail(UserVo userVo) throws MessagingException { //通过邮箱判断当前用户是否存在 @@ -97,6 +102,33 @@ public class EmailServiceImpl implements EmailService { helper.setText(templateContent, true); return message; } + /** + * 构建模板邮件 + * @param email + * @return + * @throws MessagingException + */ + public MimeMessage buildTemplateMail(Email email,String template) throws MessagingException { + //模板数据内容 + Context context = new Context(); + //插入模板数据 + for (Map.Entry entry : email.getDataMap().entrySet()) { + context.setVariable(entry.getKey(), entry.getValue()); + } + //使用的模板 + String templateContent = templateEngine.process(template, context); + MimeMessage message = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true); + //发送人 + helper.setFrom(from); + //收件人 + helper.setTo(email.getTos()); + //主题 + helper.setSubject(email.getSubject()); + //发送内容 + helper.setText(templateContent, true); + return message; + } /** * 构建邮件发送内容 diff --git a/kn-service/biz-vordm/src/main/resources/templates/forgotPassword.html b/kn-service/biz-vordm/src/main/resources/templates/forgotPassword.html new file mode 100644 index 0000000..1f6ea79 --- /dev/null +++ b/kn-service/biz-vordm/src/main/resources/templates/forgotPassword.html @@ -0,0 +1,82 @@ + + + + + 邮件模板 + + + + +
+
+

Hello, you are about to change your password!

+

Please do not disclose the verification code. His effective time is 10 minutes!

+

Your account number:

+

Your Email:

+

Your verification code:

+
+ +
+ +