Skip to content

Commit 6806ee4

Browse files
committed
completed forget password
1 parent c6b482f commit 6806ee4

File tree

6 files changed

+281
-78
lines changed

6 files changed

+281
-78
lines changed

help/2-LoginAndRegister/7-AccountSetting/7.2-ForgetPassword.md

Lines changed: 176 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,32 @@ public Map<String, Object> resetPassword(String email, String password) {
3232
clearCache(user.getId());
3333
return map;
3434
}
35+
36+
// 重置密码邮箱验证码:
37+
public Map<String, Object> getForgetCode(String email) {
38+
Map<String, Object> map = new HashMap<>();
39+
if (StringUtils.isBlank(email)) {
40+
map.put("emailMsg", "邮箱不能为空!");
41+
return map;
42+
}
43+
User user = userMapper.selectByEmail(email);
44+
if (user == null) {
45+
map.put("emailMsg", "该邮箱不存在!");
46+
return map;
47+
}
48+
if (user.getStatus() == 0) {
49+
map.put("emailMsg", "该邮箱未激活!");
50+
}
51+
// 发送邮件
52+
Context context = new Context();
53+
context.setVariable("email", email);
54+
String code = CommunityUtil.genUUID().substring(0, 4);
55+
context.setVariable("verifyCode", code);
56+
String content = templateEngine.process("/mail/forget", context);
57+
mailClient.sendMail(email, "找回密码", content);
58+
map.put("verifyCode", code);
59+
return map;
60+
}
3561
```
3662

3763
2. LoginController:
@@ -42,11 +68,35 @@ public String getForgetPage(){
4268
return "/site/forget";
4369
}
4470

71+
// 邮箱验证码
72+
@RequestMapping(path = "/forget/code", method = RequestMethod.GET)
73+
@ResponseBody
74+
public String getForgetCode(String email, HttpSession session) {
75+
Map<String, Object> map = userService.getForgetCode(email);
76+
if (map.containsKey("verifyCode")) {
77+
// 保存验证码,注意这里要对不同的邮箱保存不同的验证码,防止换邮箱后验证码还是之前的
78+
session.setAttribute(email + "_verifyCode", map.get("verifyCode"));
79+
return CommunityUtil.getJSONString(0);
80+
} else {
81+
return CommunityUtil.getJSONString(1, (String) map.get("emailMsg"));
82+
}
83+
}
84+
4585
@RequestMapping(path = "/forgetPassword", method = RequestMethod.POST)
46-
public String updatePassword(String email, String password ,Model model){
86+
public String resetPassword(String email, String verifyCode, String password, Model model, HttpSession session) {
87+
// 检查验证码
88+
String code = (String) session.getAttribute(email + "_verifyCode");
89+
if (StringUtils.isBlank(verifyCode) || StringUtils.isBlank(code) || !code.equalsIgnoreCase(verifyCode)) {
90+
// 验证码错误,返回重置密码页面
91+
model.addAttribute("codeMsg", "验证码错误!");
92+
return "/site/forget";
93+
}
94+
4795
Map<String, Object> map = userService.resetPassword(email, password);
4896
if (map == null || map.isEmpty()) {
49-
return "redirect:/logout";
97+
model.addAttribute("msg", "重置密码成功,正在前往登录页面,请重新登录!");
98+
model.addAttribute("target", "/login");
99+
return "/site/operate-result";
50100
} else {
51101
model.addAttribute("emailMsg", map.get("emailMsg"));
52102
model.addAttribute("passwordMsg", map.get("passwordMsg"));
@@ -66,68 +116,135 @@ forget.html:
66116
```html
67117
<!doctype html>
68118
<html lang="en" xmlns:th="https://www.thymeleaf.org">
119+
<head>
120+
<meta charset="utf-8">
121+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
122+
<meta name="_csrf" th:content="${_csrf.token}">
123+
<meta name="_csrf_header" th:content="${_csrf.headerName}">
124+
<link rel="icon" th:href="@{/img/icon.png}"/>
125+
<link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}" />
126+
<link rel="stylesheet" th:href="@{/css/global.css}" />
127+
<link rel="stylesheet" th:href="@{/css/login.css}" />
128+
<title>忘记密码</title>
129+
</head>
130+
<body>
131+
<div class="nk-container">
132+
<!-- 头部 -->
133+
<header class="bg-dark sticky-top" th:replace="index::header">
134+
</header>
135+
136+
<!-- 内容 -->
137+
<div class="main">
138+
<div class="container pl-5 pr-5 pt-3 pb-3 mt-3 mb-3">
139+
<form class="mt-5" th:action="@{/forgetPassword}" method="post">
140+
<div class="form-group row">
141+
<label for="your-email" class="col-sm-2 col-form-label text-right">邮箱:</label>
142+
<div class="col-sm-10">
143+
<input type="email" th:class="|form-control ${emailMsg!=null?'is-invalid':''}|"
144+
th:value="${param.email}"
145+
id="your-email" placeholder="请输入您的邮箱!" name="email" required>
146+
<div class="invalid-feedback" th:text="${emailMsg}">
147+
该邮箱已被注册!
148+
</div>
149+
</div>
150+
</div>
151+
<div class="form-group row mt-4">
152+
<label for="verifycode" class="col-sm-2 col-form-label text-right">验证码:</label>
153+
<div class="col-sm-6">
154+
<input type="text" th:class="|form-control ${codeMsg!=null?'is-invalid':''}|"
155+
th:value="${param.verifyCode}" name="verifyCode" id="verifycode"
156+
placeholder="请输入验证码!">
157+
<div class="invalid-feedback" th:text="${codeMsg}">
158+
验证码不正确!
159+
</div>
160+
</div>
161+
<div class="col-sm-4">
162+
<a href="javascript:;" id="verifyCodeBtn" class="btn btn-info form-control">获取验证码</a>
163+
</div>
164+
</div>
165+
<div class="form-group row mt-4">
166+
<label for="your-password" class="col-sm-2 col-form-label text-right">新密码:</label>
167+
<div class="col-sm-10">
168+
<input type="password" th:class="|form-control ${passwordMsg!=null?'is-invalid':''}|"
169+
th:value="${param.password}"
170+
id="your-password" placeholder="请输入新的密码!" name="password" required>
171+
<div class="invalid-feedback" th:text="${passwordMsg}">
172+
密码长度不能小于8位!
173+
</div>
174+
</div>
175+
</div>
176+
<div class="form-group row mt-4">
177+
<div class="col-sm-2"></div>
178+
<div class="col-sm-10 text-center">
179+
<button type="submit" class="btn btn-info text-white form-control">重置密码</button>
180+
</div>
181+
</div>
182+
</form>
183+
</div>
184+
</div>
185+
186+
<!-- 尾部 -->
187+
<footer class="bg-dark" th:replace="index::footer">
188+
</footer>
189+
</div>
190+
191+
<script th:src="@{/js/jquery-3.1.0.min.js}"></script>
192+
<script type="module" th:src="@{/js/popper.min.js}"></script>
193+
<script th:src="@{/js/bootstrap.min.js}"></script>
194+
<script th:src="@{/js/global.js}"></script>
195+
<script th:src="@{/js/forget.js}"></script>
196+
</body>
197+
</html>
198+
```
199+
200+
forget.js:
201+
202+
```javascript
203+
$(function(){
204+
$("#verifyCodeBtn").click(getVerifyCode);
205+
});
206+
207+
function getVerifyCode() {
208+
var email = $("#your-email").val();
209+
210+
if(!email) {
211+
alert("请先填写您的邮箱!");
212+
return false;
213+
}
214+
215+
$.get(
216+
CONTEXT_PATH + "/forget/code",
217+
{"email":email},
218+
function(data) {
219+
data = $.parseJSON(data);
220+
if(data.code == 0) {
221+
alert("验证码已发送至您的邮箱,请登录邮箱查看!");
222+
} else {
223+
alert(data.msg);
224+
}
225+
}
226+
);
227+
}
228+
```
229+
230+
邮箱内容:
231+
232+
```html
233+
<!doctype html>
234+
<html lang="en" xmlns:th="http://www.thymeleaf.org">
69235
<head>
70236
<meta charset="utf-8">
71-
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
72-
<meta name="_csrf" th:content="${_csrf.token}">
73-
<meta name="_csrf_header" th:content="${_csrf.headerName}">
74-
<link rel="icon" th:href="@{/img/icon.png}"/>
75-
<link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}" />
76-
<link rel="stylesheet" th:href="@{/css/global.css}" />
77-
<link rel="stylesheet" th:href="@{/css/login.css}" />
78237
<title>忘记密码</title>
79238
</head>
80239
<body>
81-
<div class="nk-container">
82-
<!-- 头部 -->
83-
<header class="bg-dark sticky-top" th:replace="index::header">
84-
</header>
85-
86-
<!-- 内容 -->
87-
<div class="main">
88-
<div class="container pl-5 pr-5 pt-3 pb-3 mt-3 mb-3">
89-
<form class="mt-5" th:action="@{/forgetPassword}" method="post">
90-
<div class="form-group row">
91-
<label for="your-email" class="col-sm-2 col-form-label text-right">邮箱:</label>
92-
<div class="col-sm-10">
93-
<input type="email" th:class="|form-control ${emailMsg!=null?'is-invalid':''}|"
94-
th:value="${param.email}"
95-
id="your-email" placeholder="请输入您的邮箱!" name="email" required>
96-
<div class="invalid-feedback" th:text="${emailMsg}">
97-
该邮箱已被注册!
98-
</div>
99-
</div>
100-
</div>
101-
<div class="form-group row mt-4">
102-
<label for="your-password" class="col-sm-2 col-form-label text-right">新密码:</label>
103-
<div class="col-sm-10">
104-
<input type="password" th:class="|form-control ${passwordMsg!=null?'is-invalid':''}|"
105-
th:value="${param.password}"
106-
id="your-password" placeholder="请输入新的密码!" name="password" required>
107-
<div class="invalid-feedback" th:text="${passwordMsg}">
108-
密码长度不能小于8位!
109-
</div>
110-
</div>
111-
</div>
112-
<div class="form-group row mt-4">
113-
<div class="col-sm-2"></div>
114-
<div class="col-sm-10 text-center">
115-
<button type="submit" class="btn btn-info text-white form-control">重置密码</button>
116-
</div>
117-
</div>
118-
</form>
119-
</div>
120-
</div>
121-
122-
<!-- 尾部 -->
123-
<footer class="bg-dark" th:replace="index::footer">
124-
</footer>
125-
</div>
126-
127-
<script th:src="@{/js/jquery-3.1.0.min.js}"></script>
128-
<script type="module" th:src="@{/js/popper.min.js}"></script>
129-
<script th:src="@{/js/bootstrap.min.js}"></script>
130-
<script th:src="@{/js/global.js}"></script>
240+
<div>
241+
<p>
242+
<b th:text="${email}">[email protected]</b>, 您好!
243+
</p>
244+
<p>
245+
您正在找回账号的密码,本次操作的验证码为 <b th:text="${verifyCode}">u5s6dt</b>,请您及时设置新密码!
246+
</p>
247+
</div>
131248
</body>
132249
</html>
133250
```

src/main/java/com/nowcoder/community/controller/LoginController.java

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import jakarta.servlet.http.Cookie;
1212
import jakarta.servlet.http.HttpServletRequest;
1313
import jakarta.servlet.http.HttpServletResponse;
14+
import jakarta.servlet.http.HttpSession;
1415
import org.apache.commons.lang3.StringUtils;
1516
import org.slf4j.Logger;
1617
import org.slf4j.LoggerFactory;
@@ -21,10 +22,7 @@
2122
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
2223
import org.springframework.stereotype.Controller;
2324
import org.springframework.ui.Model;
24-
import org.springframework.web.bind.annotation.CookieValue;
25-
import org.springframework.web.bind.annotation.PathVariable;
26-
import org.springframework.web.bind.annotation.RequestMapping;
27-
import org.springframework.web.bind.annotation.RequestMethod;
25+
import org.springframework.web.bind.annotation.*;
2826

2927
import javax.imageio.ImageIO;
3028
import java.awt.image.BufferedImage;
@@ -182,11 +180,35 @@ public String getForgetPage(){
182180
return "/site/forget";
183181
}
184182

183+
// 邮箱验证码
184+
@RequestMapping(path = "/forget/code", method = RequestMethod.GET)
185+
@ResponseBody
186+
public String getForgetCode(String email, HttpSession session) {
187+
Map<String, Object> map = userService.getForgetCode(email);
188+
if (map.containsKey("verifyCode")) {
189+
// 保存验证码,注意这里要对不同的邮箱保存不同的验证码,防止换邮箱后验证码还是之前的
190+
session.setAttribute(email + "_verifyCode", map.get("verifyCode"));
191+
return CommunityUtil.getJSONString(0);
192+
} else {
193+
return CommunityUtil.getJSONString(1, (String) map.get("emailMsg"));
194+
}
195+
}
196+
185197
@RequestMapping(path = "/forgetPassword", method = RequestMethod.POST)
186-
public String updatePassword(String email, String password ,Model model){
198+
public String resetPassword(String email, String verifyCode, String password, Model model, HttpSession session) {
199+
// 检查验证码
200+
String code = (String) session.getAttribute(email + "_verifyCode");
201+
if (StringUtils.isBlank(verifyCode) || StringUtils.isBlank(code) || !code.equalsIgnoreCase(verifyCode)) {
202+
// 验证码错误,返回重置密码页面
203+
model.addAttribute("codeMsg", "验证码错误!");
204+
return "/site/forget";
205+
}
206+
187207
Map<String, Object> map = userService.resetPassword(email, password);
188208
if (map == null || map.isEmpty()) {
189-
return "/site/login";
209+
model.addAttribute("msg", "重置密码成功,正在前往登录页面,请重新登录!");
210+
model.addAttribute("target", "/login");
211+
return "/site/operate-result";
190212
} else {
191213
model.addAttribute("emailMsg", map.get("emailMsg"));
192214
model.addAttribute("passwordMsg", map.get("passwordMsg"));

src/main/java/com/nowcoder/community/service/UserService.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,32 @@ public Map<String, Object> resetPassword(String email, String password) {
220220
return map;
221221
}
222222

223+
// 重置密码邮箱验证码:
224+
public Map<String, Object> getForgetCode(String email) {
225+
Map<String, Object> map = new HashMap<>();
226+
if (StringUtils.isBlank(email)) {
227+
map.put("emailMsg", "邮箱不能为空!");
228+
return map;
229+
}
230+
User user = userMapper.selectByEmail(email);
231+
if (user == null) {
232+
map.put("emailMsg", "该邮箱不存在!");
233+
return map;
234+
}
235+
if (user.getStatus() == 0) {
236+
map.put("emailMsg", "该邮箱未激活!");
237+
}
238+
// 发送邮件
239+
Context context = new Context();
240+
context.setVariable("email", email);
241+
String code = CommunityUtil.genUUID().substring(0, 4);
242+
context.setVariable("verifyCode", code);
243+
String content = templateEngine.process("/mail/forget", context);
244+
mailClient.sendMail(email, "找回密码", content);
245+
map.put("verifyCode", code);
246+
return map;
247+
}
248+
223249
// 更新密码 - not forget
224250
public Map<String, Object> updatePassword(int userId, String oldPassword, String newPassword1, String newPassword2){
225251
Map<String, Object> map = new HashMap<>();
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
$(function(){
2+
$("#verifyCodeBtn").click(getVerifyCode);
3+
});
4+
5+
function getVerifyCode() {
6+
var email = $("#your-email").val();
7+
8+
if(!email) {
9+
alert("请先填写您的邮箱!");
10+
return false;
11+
}
12+
13+
$.get(
14+
CONTEXT_PATH + "/forget/code",
15+
{"email":email},
16+
function(data) {
17+
data = $.parseJSON(data);
18+
if(data.code == 0) {
19+
alert("验证码已发送至您的邮箱,请登录邮箱查看!");
20+
} else {
21+
alert(data.msg);
22+
}
23+
}
24+
);
25+
}

0 commit comments

Comments
 (0)