wang-hao-jie
2021-10-19 cc8111dbc369c1e82f159027ee8438912ae28128
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package cn.exrick.xboot.base.controller.manage;
 
import cn.exrick.xboot.core.common.constant.CommonConstant;
import cn.exrick.xboot.core.common.constant.SettingConstant;
import cn.exrick.xboot.core.common.exception.XbootException;
import cn.exrick.xboot.core.common.redis.RedisTemplateHelper;
import cn.exrick.xboot.core.common.utils.*;
import cn.exrick.xboot.core.common.vo.EmailValidate;
import cn.exrick.xboot.core.common.vo.Result;
import cn.exrick.xboot.core.entity.Setting;
import cn.exrick.xboot.core.entity.User;
import cn.exrick.xboot.core.service.SettingService;
import cn.exrick.xboot.core.service.UserService;
import cn.exrick.xboot.core.vo.OtherSetting;
import cn.hutool.core.util.StrUtil;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
 
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;
 
/**
 * @author Exrickx
 */
@Slf4j
@RestController
@Api(tags = "邮箱验证接口")
@RequestMapping("/xboot/email")
@Transactional
public class EmailValidateController {
 
    @Autowired
    private EmailUtil emailUtil;
 
    @Autowired
    private RedisTemplateHelper redisTemplate;
 
    @Autowired
    private UserService userService;
 
    @Autowired
    private IpInfoUtil ipInfoUtil;
 
    @Autowired
    private SettingService settingService;
 
    @Autowired
    private SecurityUtil securityUtil;
 
    public OtherSetting getOtherSetting() {
 
        Setting setting = settingService.get(SettingConstant.OTHER_SETTING);
        if (StrUtil.isBlank(setting.getValue())) {
            throw new XbootException("系统未配置访问域名,请联系管理员");
        }
        return new Gson().fromJson(setting.getValue(), OtherSetting.class);
    }
 
    @RequestMapping(value = "/sendEditCode/{email}", method = RequestMethod.GET)
    @ApiOperation(value = "发送修改邮箱验证码")
    public Result<Object> sendEditCode(@PathVariable String email,
                                       HttpServletRequest request) {
 
        return sendEmailCode(email, "修改邮箱", "【XBoot】修改邮箱验证", "code-email", request);
    }
 
    @RequestMapping(value = "/sendResetCode/{email}", method = RequestMethod.GET)
    @ApiOperation(value = "发送重置密码邮箱验证码")
    public Result<Object> sendResetCode(@PathVariable String email,
                                        HttpServletRequest request) {
 
        return sendEmailCode(email, "重置密码", "【XBoot】重置密码邮箱验证", "code-email", request);
    }
 
    /**
     * 发送邮件验证码
     * @param email
     * @param operation
     * @param title
     * @param template
     * @param request
     * @return
     */
    public Result<Object> sendEmailCode(String email, String operation, String title, String template, HttpServletRequest request) {
 
        // 生成验证码 存入相关信息
        EmailValidate e = new EmailValidate();
        e.setOperation(operation);
        // 验证是否注册
        User user = userService.findByEmail(email);
        if ("修改邮箱".equals(operation)) {
            if (user != null) {
                return ResultUtil.error("该邮箱已绑定账号");
            }
            User u = securityUtil.getCurrUser();
            e.setUsername(u.getUsername());
        } else if ("重置密码".equals(operation)) {
            if (user == null) {
                return ResultUtil.error("该邮箱未注册");
            }
            e.setUsername(user.getUsername());
        }
 
        // IP限流 1分钟限1个请求
        String key = "sendEmailCode:" + ipInfoUtil.getIpAddr(request);
        String value = redisTemplate.get(key);
        if (StrUtil.isNotBlank(value)) {
            return ResultUtil.error("您发送的太频繁啦,请稍后再试");
        }
 
        String code = CommonUtil.getRandomNum();
        e.setCode(code);
        e.setEmail(email);
        e.setFullUrl(getOtherSetting().getDomain());
        redisTemplate.set(CommonConstant.PRE_EMAIL + email, new Gson().toJson(e, EmailValidate.class), 10L, TimeUnit.MINUTES);
 
        emailUtil.sendTemplateEmail(email, title, template, e);
        // 请求成功 标记限流
        redisTemplate.set(key, "sended", 1L, TimeUnit.MINUTES);
        return ResultUtil.success("发送成功");
    }
 
    @RequestMapping(value = "/editEmail", method = RequestMethod.POST)
    @ApiOperation(value = "修改邮箱或重置密码")
    public Result<Object> editEmail(@RequestParam String email) {
 
        User u = securityUtil.getCurrUser();
        u.setEmail(email);
        userService.update(u);
        // 删除缓存
        redisTemplate.delete("user::" + u.getUsername());
        return ResultUtil.success("修改邮箱成功");
    }
 
    @RequestMapping(value = "/resetByEmail", method = RequestMethod.POST)
    @ApiOperation(value = "通过邮箱重置密码")
    public Result<Object> resetByEmail(@RequestParam String email,
                                       @RequestParam String password,
                                       @RequestParam String passStrength) {
 
        User u = userService.findByEmail(email);
 
        // 在线DEMO所需
        if ("test".equals(u.getUsername()) || "test2".equals(u.getUsername())) {
            return ResultUtil.error("演示账号不支持重置密码");
        }
 
        String encryptPass = new BCryptPasswordEncoder().encode(password);
        u.setPassword(encryptPass);
        u.setPassStrength(passStrength);
        userService.update(u);
        // 删除缓存
        redisTemplate.delete("user::" + u.getUsername());
        return ResultUtil.success("重置密码成功");
    }
}