以redis为存储的用户登录实现(验证码登录)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

本文主要是一个学习类文章,仅是个人的学习笔记与经验积累。


提示:以下是本篇文章正文内容,下面案例可供参考

一、如何实现验证码登录

一个简单的登录页面
如图所示为一个简单的短信登录页面,我们将在后台生成验证码并进行登录。
相关代码如下

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private IUserService userService;

    @Resource
    private IUserInfoService userInfoService;

    /**
     * 发送手机验证码
     */
    @PostMapping("code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        // TODO 发送短信验证码并保存验证码
       return userService.sendCode(phone,session);

    }

    /**
     * 登录功能
     * @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
        // TODO 实现登录功能
        return userService.login(loginForm,session);
    }

    @GetMapping("/me")
    public Result me(){
        // TODO 获取当前登录的用户并返回
        UserDTO user = UserHolder.getUser();
        return Result.ok(user);
    }
package com.hmdp.dto;
import lombok.Data;
@Data
public class UserDTO {
    private Long id;
    private String nickName;
    private String icon;
}

package com.hmdp.utils;
public class RedisConstants {
    public static final String LOGIN_CODE_KEY = "login:code:";
    public static final Long LOGIN_CODE_TTL = 2L;
    public static final String LOGIN_USER_KEY = "login:token:";
    public static final Long LOGIN_USER_TTL = 36000L;
    public static final Long CACHE_NULL_TTL = 2L;
    public static final Long CACHE_SHOP_TTL = 30L;
    public static final String CACHE_SHOP_KEY = "cache:shop:";
    public static final String LOCK_SHOP_KEY = "lock:shop:";
    public static final Long LOCK_SHOP_TTL = 10L;
    public static final String SECKILL_STOCK_KEY = "seckill:stock:";
    public static final String BLOG_LIKED_KEY = "blog:liked:";
    public static final String FEED_KEY = "feed:";
    public static final String SHOP_GEO_KEY = "shop:geo:";
    public static final String USER_SIGN_KEY = "sign:";
}

实现短信验证登录首先要了解登录过程应该是怎样的,如图:
在这里插入图片描述
一步一步来:
在输入框输入手机号后进行校验

public Result sendCode(String phone, HttpSession session) {
        //1.校验手机号
        if (RegexUtils.isPhoneInvalid((phone))) {
            //2.不符合,返回错误信息
            return Result.fail("格式错误");
        }
   }
手机号、验证码、邮箱等校验通常通过正则表达式进行校验,RegexUtils为自行写的工具类,故不在此演示。

若符合条件,则生成验证码。

public Result sendCode(String phone, HttpSession session) {
        //1.校验手机号
        if (RegexUtils.isPhoneInvalid((phone))) {
            //2.不符合,返回错误信息
            return Result.fail("格式错误");
        }

        //3.符合 生成6位验证码
        String code = RandomUtil.randomNumbers(6);
        }

最后保存到redis里面

 public Result sendCode(String phone, HttpSession session) {
        //1.校验手机号
        if (RegexUtils.isPhoneInvalid((phone))) {
            //2.不符合,返回错误信息
            return Result.fail("格式错误");
        }

        //3.符合 生成验证码
        String code = RandomUtil.randomNumbers(6);
        //4.保存验证码redis
       stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL,TimeUnit.MINUTES);
        //5.发送验证码成功
        log.debug("发送验证码成功"+code);
        //6.返回ok
        return Result.ok();
    }

接着是对登录功能的完善
同理,先分析登录的流程
在这里插入图片描述

@Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {
        String phone = loginForm.getPhone();
        //1.手机号验证
        if (RegexUtils.isPhoneInvalid(phone)) {
            return Result.fail("格式错误");
        }
        //2.redis获取并验证码校验
        Object Cahecode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY+phone);
        String code = loginForm.getCode();
        if (Cahecode ==null || !Cahecode.toString().equals(code)) {
            //3.不一致 报错
            return Result.fail("验证码错误");
        }
        //4.查询用户
        User user = query().eq("phone", phone).one();
        //5.判断用户是否存在
        if (user == null) {
            //不存在,创建新用户
            user = createUserPhone(phone);
        }
        //保存进redis
        //随机生成token,作为登录令牌
        String token = UUID.randomUUID().toString(true);
        //将user对象转为hash存储
        UserDTO userDTO = BeanUtil.copyProperties(user,UserDTO.class);
        Map<String, Object> usertMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName,fieldValue)->
       fieldValue.toString()));//使用工具将value转为String类 id为long型会报错 开头已经给出了类型。

        //存储
        stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY+token,usertMap);
        //设置有效期
        String tokenkey= LOGIN_USER_KEY+token;
        stringRedisTemplate.expire(tokenkey,LOGIN_USER_TTL,TimeUnit.MINUTES);

        return Result.ok(token);
    }

    private User createUserPhone(String phone) {
        //1.创建用户
        User user = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(8));
        //2.保存用户
        save(user);
        return user;
    }
登录时手机号需要二次验证,确保登录的是你发送验证码的手机号。接着通过redis取出验证码校验,若验证码错误则报错。若正确,则查询用户(mybatisplus用法),不存在,创建新用户(随机生成用户名)。
Token生成为最重要的一部分内容,将它随机生成并设定刷新时间储存到redis里面(copyproties 将user的内容拷贝到UserDTO,以达到隐藏用户信息的目的)。最后设置刷新时间。

总结

短信登录验证是比较常用的登录验证方式,是个人觉得需要掌握的一个点,redis也是各个企业都在用的数据库类型,相较于传统的登录验证,比较典型。有练习和研究的价值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值