- 使用Redis存储验证码
- 验证码需要频繁访问和封信,对性能要求高;
- 验证码不需要永久保存,通常在很短时间内失效;
- 分布式部署,存在Session共享问题;
- 使用Redis存储登陆凭证
- 处理每次请求时,都要查询用户登陆凭证,访问频率非常高;
- 使用Redis缓存用户信息
- 处理每次请求时,都要根据凭证查询用户信息,访问频率非常高。
- 查询缓存中是否有user;
- 如果没有就初始化缓存;
- 如果user的信息更新,将清除缓存;
- 处理每次请求时,都要根据凭证查询用户信息,访问频率非常高。
1. 使用Redis存储验证码
- 在生成验证码的逻辑中,owner由UUID生成,并交给Cookie;然后将验证码text存到kaptcha:owner键中,并设置有效时间为60秒
@RequestMapping(path="/kaptcha", method = RequestMethod.GET)
public void getKaptcha(HttpServletResponse response, HttpSession session){
// 生成验证码
String text = kaptchaProducer.createText();
BufferedImage image = kaptchaProducer.createImage(text);
// 将验证码存入session
// session.setAttribute("kaptcha", text);
// 优化:存到redis里
// 验证码的归属owner
String kaptchaOwner = CommunityUtil.generateUUID();
Cookie cookie = new Cookie("kaptchaOwner",kaptchaOwner);
cookie.setMaxAge(60);
cookie.setPath(context_path);
response.addCookie(cookie);
String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
redisTemplate.opsForValue().set(redisKey, text, 60, TimeUnit.SECONDS);
// 将图片输出给浏览器
response.setContentType("image/png");
try{
OutputStream os = response.getOutputStream();
ImageIO.write(image, "png", os);
} catch (IOException e) {
logger.error("响应验证码失败:"+e.getMessage());
}
}
- 在登陆功能中,键从cookie中去哪出,然后从redis中获取kaptcha:kaptchaOwner键对应的值(验证码),判断验证码是否正确;
@RequestMapping(path = "/login", method = RequestMethod.POST)
public String login(String username, String password, String code, boolean rememberme,
Model model, HttpSession session, HttpServletResponse response, @CookieValue("kaptchaOwner") String kaptchaOwner){
// 从Session中取并检查验证码 --> 优化:从Redis中取
// String kaptcha = (String) session.getAttribute("kaptcha");
String kaptcha = null;
if(StringUtils.isNotBlank(kaptchaOwner)){
String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
kaptcha = (String) redisTemplate.opsForValue().get(redisKey);
}
if(StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equals(code)){
model.addAttribute("codeMsg","验证码不正确");
return "/site/login";
}
......
......
......
......
2. 使用Redis存储登陆凭证
各个逻辑验证通过后,将生成一个用户凭证(UUID生成),存到Redis中,并设置生存周期。在后续需要验证登陆逻辑时,从Redis中get即可。文章来源地址https://www.toymoban.com/news/detail-708930.html
public Map<String,Object> login(String username, String password, int expiredSeconds){
Map<String,Object> map = new HashMap<>();
// 空值判断
....
....
// 账号密码都不为空,验证合法性
// 验证账号合法性
.....
.....
// 验证密码
....
....
// 生成登陆凭证
LoginTicket loginTicket = new LoginTicket();
loginTicket.setUserId(user.getId());
loginTicket.setTicket(CommunityUtil.generateUUID());
loginTicket.setStatus(0);
loginTicket.setExpired(new Date(System.currentTimeMillis() + 1000 * 60 * 10));
loginTicketMapper.insertLoginTicket(loginTicket);
String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket());
redisTemplate.opsForValue().set(redisKey,loginTicket);
map.put("ticket", loginTicket.getTicket());
return map;
}
3. 使用Redis缓存用户信息
// 1. 优先从缓存中取值
public User getCache(int userId){
String redisKey = RedisKeyUtil.getUserKey(userId);
return (User) redisTemplate.opsForValue().get(redisKey);
}
// 2. 如果取不到就初始化缓存
public User initCache(int userId){
User user = userMapper.selectById(userId);
String redisKey = RedisKeyUtil.getUserKey(userId);
redisTemplate.opsForValue().set(redisKey, user, 3600, TimeUnit.SECONDS);
return user;
}
// 3. 数据变更时清除缓存数据
public void clearCache(int userId){
String redisKey = RedisKeyUtil.getUserKey(userId);
redisTemplate.delete(redisKey);
}
- 当获取user的时候,例如根据userId获取用户信息,先判断缓存中查有没有user:userId这个键。如果有,就从缓存中返回User;如果没有,就初始化缓存,将User信息写入user:userId。
- 每次用户信息修改后,例如更改密码后、退出登录修改ticket后、修改用户激活状态后等,多需要做一次clearCache。
文章来源:https://www.toymoban.com/news/detail-708930.html
到了这里,关于【Java Web】用Redis优化登陆模块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!