当前位置: 首页 > 后端技术 > Java

Redis实践(一)实现登录

时间:2023-04-01 23:22:54 Java

redis实践(一)实现登录这段代码值得学习,搬过来就是我的了。背景部分项目的登录逻辑如上图所示,但实际访问量越来越大,不可避免地需要一个tomcat集群,但多个Tomcat不共享session存储空间,请求时会造成数据丢失切换到不同tomcat服务的问题。所以需要数据共享,内存存储,key和value结构。基于redis的登录流程登录代码实现发送验证码@OverridepublicResultsendCode(Stringphone,HttpSessionsession){//1.检查电话号码if(RegexUtils.isPhoneInvalid(phone)){//2.如果不匹配,返回错误信息returnResult.fail("手机号码格式错误");}//3。满足生成的验证码Stringcode=RandomUtil.randomNumbers(6);//4。保存验证码到redis//setkeyvalueex120stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL,TimeUnit.MINUTES);//5。模拟发送验证码log.debug("发送验证码成功,验证码为{}",code);//返回okreturnResult.ok();}登录的实现首先检查验证码,如果验证码正确,则验证用户,如果用户不存在,则添加数据库操作。//1。查看电话号码Stringphone=loginForm.getPhone();if(RegexUtils.isPhoneInvalid(phone)){returnResult.fail("电话号码不正确");}//2。从Redis获取验证码并查看验证码StringcacheCode=stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY+phone);字符串代码=loginForm.getCode();if(cacheCode==null||!cacheCode.equals(code)){returnResult.fail("验证码错误");}//查询数据库用户user=query().eq("phone",phone).one();//如果用户不存在则创建一个新用户并保存到数据库中if(user==null){//createUserWithPhone创建用户函数user=createUserWithPhone(phone);}然后将用户信息添加到redis中。具体思路就是根据自己的规则生成一个token作为用户的凭证。这个凭证需要返回给前端,需要和前端约定好,每个异步请求都需要携带这个token。这里存储在redis中的key是token,value是用户的基本信息。//保存信息到redis//随机生成一个token作为登录token//hutool中的方法,为true则不带下划线Stringtoken=UUID.randomUUID().toString(true);//调用User对象进行Hash存储,函数用法是将用户对象转换成UserDTO(用户的基本信息存在)UserDTOuserDTO=BeanUtil.copyProperties(user,UserDTO.class);//hutool:将userDTO对象转换成map//该方法可以自定义key和valueMapuserMap=BeanUtil.beanToMap(userDTO,newHashMap<>(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue)->fieldValue.toString()));//存储字符串tokenKey=LOGIN_USER_KEY+token;stringRedisTemplate.opsForHash().putAll(tokenKey,userMap);//设置有效期stringRedisTemplate.expire(LOGIN_USER_KEY+token,30,TimeUnit.MINUTES);返回Result.ok(令牌);基于Redis登录验证实现思路,这里将登录验证交给拦截器,但是这里需要考虑Redistoken的过期。每一次异步请求都需要刷新token过期时间。这里可以使用两个拦截器。实现代码的第一个拦截器,先获取请求头中的token,然后将用户信息放入ThreadLocal//1。获取请求头中的tokenStringtoken=request.getHeader("authorization");if(StrUtil.isBlank(token)){//未登录,也未被拦截//response.setStatus(401);返回真;}//2。redis中根据token获取用户MapuserMap=stringRedisTemplate.opsForHash().entries(RedisConstants.LOGIN_USER_KEY+token);//3。判断用户是否存在if(userMap.isEmpty()){//4.不存在,不拦截,不返回401状态码//response.setStatus(401);返回真;}//5.将查询到的Hash数据转换为UserDTO对象UserDTOuserDTO=BeanUtil.fillBeanWithMap(userMap,newUserDTO(),false);//6.存在,将用户信息保存到ThreadLocalUserHolder.saveUser(userDTO);//刷新令牌stringRedisTemplate.expire(RedisConstants.LOGIN_USER_KEY+token,RedisConstants.LOGIN_USER_TTL,TimeUnit.MINUTES);返回真;第二个拦截器//判断是否拦截(ThreadLocal中用户是否存在)if(UserHolder.getUser()==null){//否,拦截response.setStatus(401);//拦截返回false;}//如果有用户,放手返回true;