登陆功能
核心:验证用户名,密码,生成登录凭证表记录,发送cookie给用户端,默认一天过期,其实就是分布式session。首先通过cookie查询用户,查到了就放在一个ThreadLocal里面。存验证码,用redis。
1.验证用户名密码等
publicMap<String, Object>login(Stringusername, Stringpassword, intexpiredSeconds) {
Map<String, Object>map=newHashMap<>();
if (StringUtils.isBlank(username)) {
map.put("usernameMsg", "账号不能为空!");
returnmap;
}
if (StringUtils.isBlank(password)) {
map.put("passwordMsg", "密码不能为空!");
returnmap;
}
Useruser=userMapper.selectByName(username);
if (user==null) {
map.put("usernameMsg", "该账号不存在");
returnmap;
}
if (user.getStatus() ==0) {
map.put("usernameMsg", "该账号未激活");
returnmap;
}
password=CommunityUtil.md5(password+user.getSalt());
if (!user.getPassword().equals(password)) {
map.put("passwordMsg", "密码不正确");
returnmap;
}
2.生成登录凭证
Entity
publicclassLoginTicket {
privateintid;
privateintuserId;
privateStringticket;
privateintstatus;
privateDateexpired;
mapper写点sql。然后service
LoginTicketloginTicket=newLoginTicket();
loginTicket.setUserId(user.getId());
loginTicket.setTicket(CommunityUtil.generateUUID());
loginTicket.setStatus(0);
loginTicket.setExpired(newDate(System.currentTimeMillis() +expiredSeconds*1000));
loginTicketMapper.insertLoginTicket(loginTicket);
或者这里可以存到Redis缓存里重构,提升性能
StringredisKey=RedisKeyUtil.getTicketKey(loginTicket.getTicket());
redisTemplate.opsForValue().set(redisKey, loginTicket);
Redis缓存存放验证码
@RequestMapping(path="/kaptcha", method=RequestMethod.GET)
publicvoidgetKaptcha(HttpServletResponseresponse/*, HttpSession session*/) {
Stringtext=kaptchaProducer.createText();
BufferedImageimage=kaptchaProducer.createImage(text);
//将验证码存入session
//session.setAttribute("kaptcha", text);
// 验证码归属
StringkaptchaOwner=CommunityUtil.generateUUID();
Cookiecookie=newCookie("kaptchaOwner", kaptchaOwner);
cookie.setMaxAge(60);
cookie.setPath(contextPath);
response.addCookie(cookie);
// 将验证码存入Redis
StringredisKey=RedisKeyUtil.getKaptchaKey(kaptchaOwner);
redisTemplate.opsForValue().set(redisKey, text, 60, TimeUnit.SECONDS);
//将图片输出给浏览器
response.setContentType("image/png");
try {
OutputStreamos=response.getOutputStream();
ImageIO.write(image, "png", os);
} catch (IOExceptione) {
logger.error("响应验证码失败:"+e.getMessage());
}
}
登录
@RequestMapping(path="/login", method=RequestMethod.POST)
publicStringlogin(Stringusername, Stringpassword, Stringcode, booleanrememberme, Modelmodel
/*, HttpSession session*/, HttpServletResponseresponse, @CookieValue("kaptchaOwner") StringkaptchaOwner) {
// String kaptcha = (String) session.getAttribute("kaptcha");
Stringkaptcha=null;
if (StringUtils.isNotBlank(kaptchaOwner)) {
StringredisKey=RedisKeyUtil.getKaptchaKey(kaptchaOwner);
kaptcha= (String) redisTemplate.opsForValue().get(redisKey);
}
if (StringUtils.isBlank(kaptcha) ||StringUtils.isBlank(code) ||!kaptcha.equalsIgnoreCase(code)) {
model.addAttribute("codeMsg", "验证码不正确");
return"/site/login";
}
//检查账号密码
intexpiredSeconds=rememberme?REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;
Map<String, Object>map=userService.login(username, password, expiredSeconds);
if (map.containsKey("ticket")) {
Cookiecookie=newCookie("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";
}
}
登出就直接把Status置为1就行了