当前位置: 首页>数据库>正文

redis 怎么登陆ftp redis怎么登录

Redis代替session

  • redis中设计key
  • 在使用session时,每个用户都会有自己的session,这样虽然验证码的键都是“code”,但是相互不影响,从而确保每个用户获取到的验证码只能够自己使用,当使用redis时,redis的key是共享的,不分用户,就要求在redis中存储验证码时,不能直接将验证码的键设置为"code",这样无法保证其唯一性。
  • redis中设计value
  • 到底该使用redis中什么数据类型存储数据,主要需要看数据样式和使用方式,一般会考虑使用String、Hash,String存储时,会多占一点内存空间,则相对来说Hash存储时,会少占用一点内存空间。
  • String结构:以Json字符串来存储,比较直观
  • Hash结构:,每个对象中每个字段独立存储,可以针对单个字段做CRUD
redis实现登录
发送验证码

redis 怎么登陆ftp redis怎么登录,redis 怎么登陆ftp redis怎么登录_拦截器,第1张

  • 添加redis
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
  • 设置redis的连接信息
spring:
  redis:
    host: 192.168.175.128
    port: 6379
    password: liang
    lettuce:
      pool:
        max-active: 10
        max-idle: 10
        min-idle: 1
        time-between-eviction-runs: 10s
  • 增加相关常量
/**
 * 保存验证码的redis中的key
 */
public static final String LOGIN_CODE_KEY = "login:code:";
/**
 * 验证码的过期时间
 */
public static final Long LOGIN_CODE_TTL = 2L;
  • 修改Service层
@Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean sendCode(String phone, HttpSession session) {
        //获取手机号,验证手机号是否合规
        boolean mobile = PhoneUtil.isMobile(phone);
        //不合规,则提示
        if (!mobile){
            return false;
        }
        //生成验证码
        String code = RandomUtil.randomNumbers(6);
        //保存验证码到redis,并设置过期时间
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //发送验证码,这里就通过打印验证码模拟了下发送验证码
        System.out.println("验证码:" + code);
        return true;
    }
  • 修改Controller层
@PostMapping("code")
public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
    String uuid = userService.sendCode(phone, session);
    return uuid.equals("") ? Result.fail("手机号码不合规"): Result.ok(uuid);
}
验证码登录、注册

redis 怎么登陆ftp redis怎么登录,redis 怎么登陆ftp redis怎么登录_拦截器_02,第2张

  • 增加相关常量
public static final String LOGIN_USER_KEY = "login:token:";
public static final Long LOGIN_USER_TTL = 30L;
  • 修改Service层
@Override
public String login(LoginFormDTO loginForm, HttpSession session) {
    //获取手机号
    String phone = loginForm.getPhone();
    //验证手机号是否合理
    boolean mobile = PhoneUtil.isMobile(phone);
    //如果不合理 提示
    if (!mobile){
        //提示用户手机号不合理
        return "";
    }
    //手机号合理 进行验证码验证
    String code = loginForm.getCode();
    //从redis中获取验证码
    String redisCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
    //如果验证码输入的是错误的  提示
    if (!code.equals(redisCode)){
        return "";
    }
    //如果验证码也正确 那么通过手机号进行查询
    User user = this.getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
    // 数据库中没查询到用户信息
    if (ObjectUtil.isNull(user)){
        user = new User();
        user.setPhone(phone);
        user.setNickName("user_"+ RandomUtil.randomString(10));
        this.save(user);
    }
    // 将用户信息保存到Redis中,注意避免保存用户敏感信息
    UserDTO userDTO = BeanUtil.toBean(user, UserDTO.class);
    // 设置UUID保存用户信息
    String uuid = IdUtil.fastSimpleUUID();
    // 将user对象转化为Map,同时将Map中的值存储为String类型的
    Map<String, Object> userDTOMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),
            CopyOptions.create().ignoreNullValue()
                    .setFieldValueEditor((key, value) -> value.toString()));
    stringRedisTemplate.opsForHash().putAll( LOGIN_USER_KEY + uuid, userDTOMap);
    //设置过期时间
    stringRedisTemplate.expire(LOGIN_USER_KEY + uuid, LOGIN_USER_TTL, TimeUnit.MINUTES);
    // 通过UUID生成简单的token
    String token = uuid + userDTO.getId();
    return token;
}
String login(LoginFormDTO loginForm, HttpSession session);
  • 修改Controller层
@PostMapping("/login")
public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
    String token = userService.login(loginForm, session);
    return StrUtil.isNotBlank(token) ? Result.ok(token) : Result.fail("手机号或验证码错误");
}
校验登录状态

redis 怎么登陆ftp redis怎么登录,redis 怎么登陆ftp redis怎么登录_redis 怎么登陆ftp_03,第3张

  • 修改LoginInterceptor拦截器
private StringRedisTemplate stringRedisTemplate;

/**
 * 构造函数
 * @param stringRedisTemplate
 */
public LoginInterceptor(StringRedisTemplate stringRedisTemplate) {
    this.stringRedisTemplate = stringRedisTemplate;
}

/**
 * preHandle方法的返回值决定是否放行,该方法在控制层方法执行前执行
 * @param request
 * @param response
 * @param handler
 * @return
 * @throws Exception
 */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //从请求头中获取token
    String token = request.getHeader("authorization");
    if (StrUtil.isBlank(token)){
        return false;
    }

    String uuid = token.substring(0,token.lastIndexOf("-"));
    System.out.println(uuid);
    //从redis中获取值
    Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(LOGIN_USER_KEY + uuid);
    if (ObjectUtil.isNull(entries)){
        return false;
    }
    //将map转化为UserDTO对象
    UserDTO userDTO = BeanUtil.fillBeanWithMap(entries, new UserDTO(), true);
    //将用户信息保存到 ThreadLocal
    UserHolder.saveUser(userDTO);
    return true;
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(new LoginInterceptor(stringRedisTemplate))
                //放行资源
                .excludePathPatterns(
                        "/shop/**",
                        "/voucher/**",
                        "/shop-type/**",
                        "/upload/**",
                        "/blog/hot",
                        "/user/code",
                        "/user/login"
                )
                // 设置拦截器优先级
                .order(1);
    }
}
登录状态的刷新问题
  • 因为设置了redis中存储的用户的有效期,所以在用户访问界面的时,需要更新token令牌的存活时间,例如修改LoginInterceptor拦截器,在此拦截器中刷新过期时间
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //从请求头中获取token
    String token = request.getHeader("authorization");
    if (StrUtil.isBlank(token)){
        return false;
    }

    String uuid = token.substring(0,token.lastIndexOf("-"));
    System.out.println(uuid);
    //从redis中获取值
    Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(LOGIN_USER_KEY + uuid);
    if (ObjectUtil.isNull(entries)){
        return false;
    }
    //将map转化为UserDTO对象
    UserDTO userDTO = BeanUtil.fillBeanWithMap(entries, new UserDTO(), true);
    //将用户信息保存到 ThreadLocal
    UserHolder.saveUser(userDTO);
    //刷新token有效期
    stringRedisTemplate.expire(LOGIN_USER_KEY + uuid, LOGIN_USER_TTL, TimeUnit.MINUTES);
    return true;
}
  • 但是需要注意的是,自定义的登录拦截器只是针对需要登录访问的请求进行了拦截,如果用户访问没被拦截的请求,该拦截器不会生效,则token令牌不能进行更新,当用户长时间访问不需要登录的页面,token令牌失效,再去访问被拦截的请求,则需要重新登录,这是不合理的。所有我们还需要在定义一个拦截器,进行token令牌刷新。

redis 怎么登陆ftp redis怎么登录,redis 怎么登陆ftp redis怎么登录_拦截器_04,第4张

  • 刷新令牌的Interceptor
/**
 * 刷新令牌的拦截器
 * @author liang
 */
public class RefreshTokenInterceptor implements HandlerInterceptor {

    private StringRedisTemplate redisTemplate;

    public RefreshTokenInterceptor(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //从请求头中获取token
        String token = request.getHeader("authorization");
        if (StrUtil.isBlank(token)){
            return false;
        }
        String uuid = token.substring(0, token.lastIndexOf("-"));
        //从Redis中获取值
        Map<Object, Object> userMap = redisTemplate.opsForHash().entries(LOGIN_USER_KEY + uuid);
        if (ObjectUtil.isNull(userMap)){
            return false;
        }
        //将map转换为UserDTO对象
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
        //将用户信息保存到 ThreadLocal
        UserHolder.saveUser(userDTO);
        //刷新token有效期
        redisTemplate.expire(LOGIN_USER_KEY + uuid, LOGIN_USER_TTL, TimeUnit.MINUTES);
        return true;

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }
}
  • 修改登录的Interceptor
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * preHandle方法的返回值决定是否放行,该方法在控制层方法执行前执行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        UserDTO user = UserHolder.getUser();
        return ObjectUtil.isNotNull(user);
    }
}
  • 修改WebMvcConfigurer配置类
@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Resource
    StringRedisTemplate stringRedisTemplate;

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate));
        registry.addInterceptor(new LoginInterceptor())
                //放行资源
                .excludePathPatterns(
                        "/shop/**",
                        "/voucher/**",
                        "/shop-type/**",
                        "/upload/**",
                        "/blog/hot",
                        "/user/code",
                        "/user/login"
                )
                // 设置拦截器优先级
                .order(1);
    }
}


https://www.xamrdz.com/database/6ah1963402.html

相关文章: