JAVA邮箱绑定链接激活验证

1:业务控制类
@RestController
@RequestMapping("/v2/yuan/my")
public class YuanMyApi extends BaseController {

    @Autowired
    private YuanMailRecordingService yuanMailRecordingService;

    @Autowired
    private ISysUserService sysUserService;

    @ApiOperation("邮箱绑定")
    @ApiImplicitParams({
    @ApiImplicitParam(name = "email", value = "邮箱账号", dataType = "string", paramType = "query", required = true)
    })
    @PostMapping("/relateEmail")

    public AjaxResult relateEmail(String email, String token) {
        Long userId = JwtUtils.getUserId(token);
        if (userId == null) {
            return AjaxResult.fail("登录错误").code(401).build();
        }
        SysUser sysUser = ShiroUtils.getSysUser();
        if (!sysUser.getEmail().isEmpty()) {
            return AjaxResult.ok("邮箱已绑定").build();
        }
        //邮件内容  邮箱+随机uuid的方式组成激活链接
        String link = email + UUID.randomUUID().toString().toLowerCase();
        boolean b;
        b = yuanMailRecordingService.htmlEmail(email, link);
        if (!b) {
            return AjaxResult.success("邮件发送失败");
        }
        LocalDateTime expireTime = LocalDateTime.now().plusMinutes(5);
        YuanMailRecording yuanMailRecording = YuanMailRecording.builder()
                .userId(sysUser.getUserId())
                .mail(email)
                .link(link)
                .expireTime(expireTime)
                .status(0)
                .build();
        boolean save = yuanMailRecordingService.save(yuanMailRecording);
        return AjaxResult.ok().result(save).build();
    }


@GetMapping("/checkLink")
    public AjaxResult checkLink(String link) {
        YuanMailRecording mailRecording = yuanMailRecordingService.getOne(
                new LambdaQueryWrapper<YuanMailRecording>().eq(StringUtils.isNotBlank(link), YuanMailRecording::getLink, link));
        if (mailRecording == null) {
            return AjaxResult.ok("激活失败").build();
        }
        if (mailRecording.getExpireTime().isBefore(LocalDateTime.now())) {
            return AjaxResult.ok("激活链接已过期").build();
        }
        //激活成功更改表里状态为1
        mailRecording.setStatus(1);
        //激活成功则删除link字段数据
        mailRecording.setLink("");
        boolean update = yuanMailRecordingService.updateById(mailRecording);
        SysUser sysUser = sysUserService.selectUserById(mailRecording.getUserId());
        sysUser.setEmail(mailRecording.getMail());
        sysUserService.updateUser(sysUser);
        return AjaxResult.ok("激活成功").result(update).build();
    }

}
Controller.java
2:操作类
package com.ruoyi.common.core.domain;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.utils.StringUtils;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 操作消息提醒
 * 
 * @author ruoyi
 */
public class AjaxResult extends HashMap<String, Object>
{
    private static final long serialVersionUID = 1L;

    /** 状态码 */
    public static final String CODE_TAG = "code";

    /** 返回内容 */
    public static final String MSG_TAG = "msg";

    /** 数据对象 */
    public static final String DATA_TAG = "data";

    /**
     * 时间戳
     */
    public static final String TIMESTAMP_TAG = "timestamp";

    /**
     * 状态类型
     */
    public enum Type
    {
        /** 成功 */
        SUCCESS(0),
        /** 警告 */
        WARN(301),
        /** 错误 */
        ERROR(500);
        private final int value;

        Type(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
     */
    public AjaxResult()
    {
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     * 
     * @param type 状态类型
     * @param msg 返回内容
     */
    public AjaxResult(Type type, String msg)
    {
        super.put(CODE_TAG, type.value);
        super.put(MSG_TAG, msg);
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     * 
     * @param type 状态类型
     * @param msg 返回内容
     * @param data 数据对象
     */
    public AjaxResult(Type type, String msg, Object data)
    {
        super.put(CODE_TAG, type.value);
        super.put(MSG_TAG, msg);
        if (StringUtils.isNotNull(data))
        {
            super.put(DATA_TAG, data);
        }
    }

    /**
     * 返回成功消息
     * 
     * @return 成功消息
     */
    public static AjaxResult success()
    {
        return AjaxResult.success("操作成功");
    }

    /**
     * 返回成功数据
     * 
     * @return 成功消息
     */
    public static AjaxResult success(Object data)
    {
        return AjaxResult.success("操作成功", data);
    }

    /**
     * 返回成功消息
     * 
     * @param msg 返回内容
     * @return 成功消息
     */
    public static AjaxResult success(String msg)
    {
        return AjaxResult.success(msg, null);
    }

    /**
     * 返回成功消息
     * 
     * @param msg 返回内容
     * @param data 数据对象
     * @return 成功消息
     */
    public static AjaxResult success(String msg, Object data)
    {
        return new AjaxResult(Type.SUCCESS, msg, data);
    }

    /**
     * 返回警告消息
     * 
     * @param msg 返回内容
     * @return 警告消息
     */
    public static AjaxResult warn(String msg)
    {
        return AjaxResult.warn(msg, null);
    }

    /**
     * 返回警告消息
     * 
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static AjaxResult warn(String msg, Object data)
    {
        return new AjaxResult(Type.WARN, msg, data);
    }

    /**
     * 返回错误消息
     * 
     * @return
     */
    public static AjaxResult error()
    {
        return AjaxResult.error("操作失败");
    }

    /**
     * 返回错误消息
     * 
     * @param msg 返回内容
     * @return 警告消息
     */
    public static AjaxResult error(String msg)
    {
        return AjaxResult.error(msg, null);
    }

    /**
     * 返回错误消息
     * 
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static AjaxResult error(String msg, Object data)
    {
        return new AjaxResult(Type.ERROR, msg, data);
    }

    private AjaxResult(Map<String, Object> propertiesMap) {
        for(Map.Entry<String, Object> entry : propertiesMap.entrySet()){
            this.put(entry.getKey(), entry.getValue());
        }
    }

    public static RetBuild ok(){
        return getBuild().ok();
    }

    public static RetBuild ok(String msg){
        return getBuild().ok(msg);
    }

    public static RetBuild fail(){
        return getBuild().fail();
    }

    public static RetBuild fail(String msg){
        return getBuild().fail(msg);
    }

    public static RetBuild getBuild(){
        return new RetBuild();
    }

    public static class RetBuild {

        private static final String RESULT_TAG = "result";

        private static final String LIST_TAG = "list";

        private Map<String, Object> propertiesMap = new HashMap<String, Object>();

        private Map<String, Object> dataMap = new HashMap<>();

        public RetBuild ok() {
            propertiesMap.put(CODE_TAG, Type.SUCCESS.value);
            propertiesMap.put(MSG_TAG, "操作成功");
            return this;
        }

        public RetBuild ok(String msg) {
            propertiesMap.put(CODE_TAG, Type.SUCCESS.value);
            propertiesMap.put(MSG_TAG, msg);
            return this;
        }

        public RetBuild code(int code){
            propertiesMap.put(CODE_TAG, code);
            return this;
        }

        public RetBuild fail() {
            propertiesMap.put(CODE_TAG, Type.ERROR.value);
            propertiesMap.put(MSG_TAG, "操作失败");
            return this;
        }

        public RetBuild fail(String msg) {
            propertiesMap.put(CODE_TAG, Type.ERROR.value);
            propertiesMap.put(MSG_TAG, msg);
            return this;
        }


        public RetBuild result(boolean result) {
            propertiesMap.put(RESULT_TAG, result);
            return this;
        }

        public RetBuild data(Object data) {
            propertiesMap.put(DATA_TAG, data);
            return this;
        }

        public RetBuild list(Collection<?> collection) {
            propertiesMap.put(LIST_TAG, collection);
            return this;
        }

        public RetBuild page(IPage<?> page, List<?> list){
            propertiesMap.put("total", page.getTotal());
            propertiesMap.put("rows", list);
            propertiesMap.put("pages", page.getPages());
            propertiesMap.put("current", page.getCurrent());
            propertiesMap.put("size", page.getSize());
            return this;
        }

        public RetBuild page(IPage<?> page){
            propertiesMap.put("total", page.getTotal());
            propertiesMap.put("rows", page.getRecords());
            propertiesMap.put("pages", page.getPages());
            propertiesMap.put("current", page.getCurrent());
            propertiesMap.put("size", page.getSize());
            return this;
        }

        public RetBuild proPut(String key, Object value) {
            propertiesMap.put(key, value);
            return this;
        }

        public RetBuild put(String key, Object value) {
            dataMap.put(key, value);
            return this;
        }

        public RetBuild put(Map<String, Object> map) {
            dataMap.putAll(map);
            return this;
        }

        public AjaxResult build() {
            if (StringUtils.isNotEmpty(dataMap)){
                propertiesMap.put(DATA_TAG, dataMap);
            }
            propertiesMap.put(TIMESTAMP_TAG, System.currentTimeMillis());
            return new AjaxResult(propertiesMap);
        }
    }

}
AjaxResult.java
3:权限验证工具类
package com.ruoyi.framework.jwt.utils;

import java.util.Date;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;

/**
 * jwt 工具类
 *
 * @author Licl
 */
public class JwtUtils {
    private static final long EXPIRE_TIME = 30 * 60 * 1000;

    private static final String CLAIM_NAME = "username";

    private static final String CLAIM_ID = "userId";

    public static String createToken(Long userId, String username, String password) {
        return createToken(userId, username, password, EXPIRE_TIME);
    }

    public static String createToken(Long userId, String username, String password, long expireTime) {
        Date date = new Date(System.currentTimeMillis() + expireTime);
        // 加密处理密码
        Algorithm algorithm = Algorithm.HMAC256(password);
        return JWT.create()
                .withClaim(CLAIM_NAME, username)
                .withClaim(CLAIM_ID, userId)
                .withExpiresAt(date).sign(algorithm);
    }

    public static void verify(String username, String dbPwd, String token)
    {
        Algorithm algorithm = Algorithm.HMAC256(dbPwd);
        JWTVerifier jwtVerifier = JWT.require(algorithm).withClaim(CLAIM_NAME, username).build();
        try
        {
            jwtVerifier.verify(token);
        }
        catch (TokenExpiredException e)
        {
            throw new TokenExpiredException("token已过期");
        }
        catch (JWTVerificationException e)
        {
            throw new JWTVerificationException("token验证失败");
        }
    }

    public static String getUserName(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(CLAIM_NAME).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    public static Long getUserId(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(CLAIM_ID).asLong();
        } catch (JWTDecodeException e) {
            return null;
        }
    }
}
JwtUtils.java
4:服务层接口
package com.ruoyi.yuan.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.yuan.domain.YuanMailRecording;
import org.springframework.web.multipart.MultipartFile;

/**
 * 邮箱验证记录表(YuanMailRecording)表服务接口
 *
 * @author JingLing
 * @since 2021-12-16 13:49:11
 */
public interface YuanMailRecordingService extends IService<YuanMailRecording> {

    /**
     * 发送普通邮件 (无其他资源 无html 无附件)
     *
     * @param email 发送对象
     */
    boolean commonEmail(String email, String link);

    /**
     * 发送html形式的邮件
     *
     * @param email 发送对象
     * @param link  激活链接
     * @return 统一返回ajax
     */
    boolean htmlEmail(String email, String link);

    /**
     * 带附件 邮件发送
     */
    void enclosureEmail(YuanMailRecording yuanMailRecording, MultipartFile multipartFile);

}
service.java
5:接口实现类
package com.ruoyi.yuan.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.yuan.mapper.YuanMailRecordingMapper;
import com.ruoyi.yuan.domain.YuanMailRecording;
import com.ruoyi.yuan.service.YuanMailRecordingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.internet.MimeMessage;
import java.io.File;

/**
 * 邮箱验证记录表(YuanMailRecording)表服务实现类
 *
 * @author JingLing
 * @since 2021-12-16 13:49:11
 */
@Service
@Slf4j
public class YuanMailRecordingServiceImpl extends ServiceImpl<YuanMailRecordingMapper, YuanMailRecording> implements YuanMailRecordingService {

    @Autowired
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String from;

    @Value("${spring.mail.request}")
    private String request;

    /**
     * 发送普通邮件
     *
     * @param email 发送对象
     */
    @Override
    public boolean commonEmail(String email, String link) {

        //创建简单邮件消息
        SimpleMailMessage message = new SimpleMailMessage();
        //谁发的
        message.setFrom(from);
        //接收方
        message.setTo(email);
        //激活链接
        message.setText(link);
        try {
            mailSender.send(message);
            log.info("邮件发送成功");
            return true;
        } catch (MailException e) {
            e.printStackTrace();
            log.error("邮件发送失败");
            return false;
        }
    }

    /**
     * 发送html邮件
     *
     * @param email 发送对象
     * @param link  激活链接
     */
    @Override
    public boolean htmlEmail(String email, String link) {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        try {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
            //邮件内容
            StringBuilder sb = new StringBuilder();
            sb.append("<html><head></head><body>");
            sb.append("<a href=").append(request).append("v2/yuan/my/checkLink?link=");
            sb.append(link);
            sb.append(">点击激活</a></body>");
            messageHelper.setFrom(from);
            messageHelper.setTo(email);
            messageHelper.setSubject("一封激活邮件");
            messageHelper.setText(sb.toString(), true);
            mailSender.send(mimeMessage);
            log.info("HTML邮件成功");
            return true;
        } catch (javax.mail.MessagingException e) {
            e.printStackTrace();
        }
        log.error("HTML邮件发送失败");
        return false;
    }

    /**
     * 带附件邮件发送
     */
    @Override
    public void enclosureEmail(YuanMailRecording yuanMailRecording, MultipartFile multipartFile) {
        //创建一个MINE消息
        MimeMessage message = mailSender.createMimeMessage();
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //谁发
            helper.setFrom(from);
            //谁接收
            helper.setTo(yuanMailRecording.getMail());
            //邮件内容   true 表示带有附件或html
            helper.setText(yuanMailRecording.getLink(), true);
            File multipartFileToFile = multipartFileToFile(multipartFile);
            assert multipartFileToFile != null;
            FileSystemResource file = new FileSystemResource(multipartFileToFile);
            String filename = file.getFilename();
            //添加附件
            assert filename != null;
            helper.addAttachment(filename, file);
            mailSender.send(message);
            log.info("邮件成功", yuanMailRecording.getMail() + yuanMailRecording.getLink());
        } catch (javax.mail.MessagingException e) {
            e.printStackTrace();
            log.error("附件邮件发送失败" + e.getMessage());
        }
    }

    /**
     * 将 multpartfile 转为file
     *
     * @return file
     */
    private File multipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        assert fileName != null;
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 若需要防止生成的临时文件重复,可以在文件名后添加随机码
        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
ServiceImpl.java

 

posted @ 2022-01-06 12:20  Malegej  阅读(172)  评论(0)    收藏  举报