1. 功能描述

① 访问登录页面:点击顶部区域内的链接,打开登录页面。
② 登录:验证账号、密码、验证码;成功时,生成登录凭证,发送给客户端;失败时,跳转回登录页。
③ 退出:将登录凭证修改为失效状态;跳转至网站首页。
④ 忘记密码: 点击登录页面上的“忘记密码”链接,打开忘记密码页面;在表单中输入注册的邮箱,点击获取验证码按钮,服务器为该邮箱发送一份验证码;在表单中填写收到的验证码及新密码,点击重置密码,服务器对密码进行修改。

2. 登录、退出

LoginController.java

@PostMapping("/login")
public String login(String username, String password, String code, boolean rememberme,
                    Model model, HttpSession session, HttpServletResponse response) {
    // 检查验证码
    String kaptcha = (String) session.getAttribute("kaptcha");
    if (StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) {
        model.addAttribute("codeMsg", "验证码不正确!");
        return "/site/login";
    }

    // 检查账号,密码
    int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;
    Map<String, Object> map = userService.login(username, password, expiredSeconds);
    if (map.containsKey("ticket")) {
        Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
        cookie.setPath(contextPath);
        cookie.setMaxAge(expiredSeconds);
        response.addCookie(cookie);
        return "redirect:/index";
    } else {
        model.addAttribute("usernameMsg", map.get("usernameMsg"));
        model.addAttribute("passwordMsg", map.get("passwordMsg"));
        return "/site/login";
    }
}

@GetMapping("/logout")
public String logout(@CookieValue("ticket") String ticket) {
    userService.logout(ticket);
    return "redirect:/login";
}

UserService.java

public Map<String, Object> login(String username, String password, int expiredSeconds) {
    Map<String, Object> map = new HashMap<>();

    // 空值处理
    if (StringUtils.isBlank(username)) {
        map.put("usernameMsg", "账号不能为空!");
        return map;
    }
    if (StringUtils.isBlank(password)) {
        map.put("passwordMsg", "密码不能为空!");
        return map;
    }

    // 验证账号
    User user = userMapper.selectByName(username);
    if (user == null) {
        map.put("usernameMsg", "该账号不存在!");
        return map;
    }

    // 验证状态
    if (user.getStatus() == 0) {
        map.put("usernameMsg", "该账号未激活!");
        return map;
    }

    // 验证密码
    password = CommunityUtil.md5(password + user.getSalt());
    if (!user.getPassword().equals(password)) {
        map.put("passwordMsg", "密码不正确!");
        return map;
    }

    // 生成登录凭证
    LoginTicket loginTicket = new LoginTicket();
    loginTicket.setUserId(user.getId());
    loginTicket.setTicket(CommunityUtil.generateUUID());
    loginTicket.setStatus(0);
    loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));
    loginTicketMapper.insertLoginTicket(loginTicket);

    map.put("ticket", loginTicket.getTicket());
    return map;
}

public void logout(String ticket) {
    loginTicketMapper.updateStatus(ticket, 1);
}

public LoginTicket findLoginTicket(String ticket) {
    return loginTicketMapper.selectByTicket(ticket);
}

public int updateHeader(int userId, String headerUrl) {
    return userMapper.updateHeader(userId, headerUrl);
}

login.html

<!-- 内容 -->
<div class="main">
	<div class="container pl-5 pr-5 pt-3 pb-3 mt-3 mb-3">
		<h3 class="text-center text-info border-bottom pb-3">&nbsp;&nbsp;</h3>
		<form class="mt-5" method="post" th:action="@{/login}">
			<div class="form-group row">
				<label for="username" class="col-sm-2 col-form-label text-right">账号:</label>
				<div class="col-sm-10">
					<input type="text" th:class="|form-control ${usernameMsg!=null?'is-invalid':''}|"
						   th:value="${param.username}"
						   id="username" name="username" placeholder="请输入您的账号!" required>
					<div class="invalid-feedback" th:text="${usernameMsg}">
						该账号不存在!
					</div>
				</div>
			</div>
			<div class="form-group row mt-4">
				<label for="password" class="col-sm-2 col-form-label text-right">密码:</label>
				<div class="col-sm-10">
					<input type="password" th:class="|form-control ${passwordMsg!=null?'is-invalid':''}|"
						   th:value="${param.password}"
						   id="password" name="password" placeholder="请输入您的密码!" required>
					<div class="invalid-feedback" th:text="${passwordMsg}">
						密码长度不能小于8!
					</div>							
				</div>
			</div>
			<div class="form-group row mt-4">
				<label for="verifycode" class="col-sm-2 col-form-label text-right">验证码:</label>
				<div class="col-sm-6">
					<input type="text" th:class="|form-control ${codeMsg!=null?'is-invalid':''}|"
						   id="verifycode" name="code" placeholder="请输入验证码!">
					<div class="invalid-feedback">
						验证码不正确!
					</div>
				</div>
				<div class="col-sm-4">
					<img th:src="@{/kaptcha}" id="kaptcha" style="width:100px;height:40px;" class="mr-2"/>
					<a href="javascript:refresh_kaptcha();" class="font-size-12 align-bottom">刷新验证码</a>
				</div>
			</div>				
			<div class="form-group row mt-4">
				<div class="col-sm-2"></div>
				<div class="col-sm-10">
					<input type="checkbox" id="remember-me" name="rememberme"
						   th:checked="${param.rememberme}">
					<label class="form-check-label" for="remember-me">记住我</label>
					<a href="forget.html" class="text-danger float-right">忘记密码?</a>
				</div>
			</div>				
			<div class="form-group row mt-4">
				<div class="col-sm-2"></div>
				<div class="col-sm-10 text-center">
					<button type="submit" class="btn btn-info text-white form-control">立即登录</button>
				</div>
			</div>
		</form>				
	</div>
</div>

3. 忘记密码

LoginController.java

@GetMapping("/forget/code")
@ResponseBody
public String getForgetCode(String email, HttpSession session, Model model) {
    if (StringUtils.isBlank(email)) {
        return CommunityUtil.getJSONString(1, "邮箱不能为空!");
    }
    Map<String, Object> map = userService.verifyEmail(email);
    if(map.containsKey("user")) {//判断是否有邮箱的注册信息

        // 保存验证码
        session.setAttribute("verifyCode", map.get("code"));
        return CommunityUtil.getJSONString(0);
    } else {
        return CommunityUtil.getJSONString(1, "查询不到该邮箱注册信息");
    }
}

@PostMapping("/forget/password")
public String resetPassword(String email, String verifyCode, String password, Model model, HttpSession session) {
   String code = (String) session.getAttribute("verifyCode");
    if (StringUtils.isBlank(verifyCode) || StringUtils.isBlank(code) || !code.equalsIgnoreCase(verifyCode)) {
        model.addAttribute("codeMsg", "验证码错误!");
        return "/site/forget";
    }

    Map<String, Object> map = userService.resetPassword(email, password);
    if (map.containsKey("user")) {
        model.addAttribute("msg","修改密码成功,请重新登录");
        model.addAttribute("target","/login");
        return "/site/operate-result";
    } else {
        model.addAttribute("emailMsg", map.get("emailMsg"));
        model.addAttribute("passwordMsg", map.get("passwordMsg"));
        return "/site/forget";
    }
}

UserService.java

//重置密码前校验邮箱
public Map<String, Object> verifyEmail(String email) {
    Map<String,Object> map = new HashMap<>();
    // 空值处理
    if (StringUtils.isBlank(email)) {
        //不需要写emailMsg,直接返回空的就行
        return map;
    }
    User user = userMapper.selectByEmail(email);
    if (user == null) {
        //不需要写emailMsg,直接返回空的就行
        return map;
    } else {
        //如果能查到这个邮箱就发送邮件
        Context context = new Context();
        context.setVariable("email", email);
        String code = CommunityUtil.generateUUID().substring(0, 4);
        context.setVariable("verifyCode", code);
        String content = templateEngine.process("/mail/forget", context);
        mailClient.sendMail(email, "找回密码", content);
        map.put("code", code);
    }
    map.put("user", user);
    return map;
}

// 重置密码
public Map<String, Object> resetPassword(String email, String password) {
    Map<String, Object> map = new HashMap<>();

    // 空值处理
    if (StringUtils.isBlank(email)) {
        map.put("emailMsg", "邮箱不能为空!");
        return map;
    }
    if (StringUtils.isBlank(password)) {
        map.put("passwordMsg", "密码不能为空!");
        return map;
    }

    // 验证邮箱
    User user = userMapper.selectByEmail(email);
    if (user == null) {
        map.put("emailMsg", "该邮箱尚未注册!");
        return map;
    }

    // 重置密码
    password = CommunityUtil.md5(password + user.getSalt());
    userMapper.updatePassword(user.getId(), password);

    map.put("user", user);
    return map;
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐