吉林省建设厅网站评职称系统做网站比较好的
吉林省建设厅网站评职称系统,做网站比较好的,一个做网站的软件,建设兼职网站目的Redis代替session 实现登录流程 如果使用String#xff0c;他的value#xff0c;用多占用一点空间#xff0c;如果使用哈希#xff0c;则他的value中只会存储他数据本身#xff0c;如果不是特别在意内存#xff0c;其实使用String就可以
设计key的具体细节
在设计这个k…Redis代替session 实现登录流程 如果使用String他的value用多占用一点空间如果使用哈希则他的value中只会存储他数据本身如果不是特别在意内存其实使用String就可以
设计key的具体细节
在设计这个key的时候我们之前讲过需要满足两点
key要具有唯一性key要方便携带 如果我们采用phone手机号这个的数据来存储当然是可以的但是如果把这样的敏感数据存储到redis中并且从页面中带过来毕竟不太合适所以我们在后台生成一个随机串token然后让前端带来这个token就能完成我们的整体逻辑了
整体访问流程 当注册完成后用户去登录会去校验用户提交的手机号和验证码是否一致如果一致则根据手机号查询用户信息不存在则新建最后将用户数据保存到redis并且生成token作为redis的key当我们校验用户是否登录时会去携带着token进行访问从redis中取出token对应的value判断是否存在这个数据如果没有则拦截如果存在则将其保存到threadLocal中并且放行。 基于Redis实现短信登录
UserServiceImpl代码 // public static final String LOGIN_CODE_KEY login:code:;
Override
public Result login(LoginFormDTO loginForm, HttpSession session) {// 1.校验手机号String phone loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合返回错误信息return Result.fail(手机号格式错误);}// 3.从redis获取验证码并校验String cacheCode stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY phone);String code loginForm.getCode();if (cacheCode null || !cacheCode.equals(code)) {// 不一致报错return Result.fail(验证码错误);}// 4.一致根据手机号查询用户 select * from tb_user where phone ?User user query().eq(phone, phone).one();// 5.判断用户是否存在if (user null) {// 6.不存在创建新用户并保存user createUserWithPhone(phone);}// 7.保存用户信息到 redis中// 7.1.随机生成token作为登录令牌String token UUID.randomUUID().toString(true);// 7.2.将User对象转为HashMap存储UserDTO userDTO BeanUtil.copyProperties(user, UserDTO.class);MapString, Object userMap BeanUtil.beanToMap(userDTO, new HashMap(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName, fieldValue) - fieldValue.toString()));// 7.3.存储String tokenKey LOGIN_USER_KEY token;stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);// 7.4.设置token有效期stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.返回tokenreturn Result.ok(token);
}
解决状态登录刷新问题 在这个方案中他确实可以使用对应路径的拦截同时刷新登录token令牌的存活时间但是现在这个拦截器他只是拦截需要被拦截的路径假设当前用户访问了一些不需要拦截的路径那么这个拦截器就不会生效所以此时令牌刷新的动作实际上就不会执行所以这个方案他是存在问题的 既然之前的拦截器无法对不需要拦截的路径生效那么我们可以添加一个拦截器在第一个拦截器中拦截所有的路径把第二个拦截器做的事情放入到第一个拦截器中同时刷新令牌因为第一个拦截器有了threadLocal的数据所以此时第二个拦截器只需要判断拦截器中的user对象是否存在即可完成整体刷新功能。
RefreshTokenInterceptor
public class RefreshTokenInterceptor implements HandlerInterceptor {private StringRedisTemplate stringRedisTemplate;public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取请求头中的tokenString token request.getHeader(authorization);if (StrUtil.isBlank(token)) {return true;}// 2.基于TOKEN获取redis中的用户String key LOGIN_USER_KEY token;MapObject, Object userMap stringRedisTemplate.opsForHash().entries(key);// 3.判断用户是否存在if (userMap.isEmpty()) {return true;}// 5.将查询到的hash数据转为UserDTOUserDTO userDTO BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);// 6.存在保存用户信息到 ThreadLocalUserHolder.saveUser(userDTO);// 7.刷新token有效期stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.放行return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserHolder.removeUser();}
}
LoginInterceptor
public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.判断是否需要拦截ThreadLocal中是否有用户if (UserHolder.getUser() null) {// 没有需要拦截设置状态码response.setStatus(401);// 拦截return false;}// 有用户则放行return true;}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/86250.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!