这么玩Springboot+Redis+腾讯云短信验证码登录

在很多网站上都提供了短信验证码登录的功能,其思路大概是这样的:

  • 前台点击发送验证码(会携带手机号)
  • 调用后台接口生成验证码(3分钟有效),并将验证码存入缓存当中(这里用的是redis)
  • 根据前台传送的手机号发送验证码
  • 用户收到验证码之后填写验证码并登陆
  • 后台收到登陆请求,先校验校正码是否有效并且正确
  • 验证码校验通过之后有两种情况:
    • 查询数据库,用户存在,则登录成功
    • 用户不存在,跳转到注册页面

流程如下:

一、 首先创建一个SpringBoot项目,导入以下依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>org.example</groupId>
    <artifactId>messageTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
<!--        springboot启动依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
<!--        springboot测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


<!--        合成SpringMVC功能-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

<!--        lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--springboot集成redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!--腾讯云短信服务SDK-->
        <dependency>
            <groupId>com.github.qcloudsms</groupId>
            <artifactId>qcloudsms</artifactId>
            <version>1.0.2</version>
        </dependency>
        
    </dependencies>
</project>
二、查看腾讯云短信的参数配置信息,并在application.yml文件中配置

注:腾讯云短信服务是需要申请签名和模板的,如果没有申请,就去申请一个,如果有企业的话很好注册,如果是个人的话,需要先去微信公众平台
申请一个订阅号或者服务号(他们都属于微信公众号,但是我好像记得个人只能申请订阅号),申请成功之后,就可以用这个公众号去申请腾讯云的短信服务(确实挺恶心的,毕竟是一家公司
申请成功之后:
在这里插入图片描述
查找自己的:
SDK AppID :******
App Key:******
TEMPLATE_ID(模版ID) :******
1、模板ID如下:
在这里插入图片描述
2、配置application.yml文件

server:
  port: 8080

spring:
  redis:
    host: 127.0.0.1
    port: 6379

smsConfig:
  appId: 1400557427  #腾讯云短信应用id
  appkey: dbae4fa0a746c533a48a7f67ebf504c7  #腾讯云短信应用key
  smsSign: 华达州猛学java公众号              #腾讯云短信的签名模板
  templateId: 1067012
  invalidTime: 300

3、再创建一个SmsConfigProperties类读取配置文件中的值

/**
 * @ClassName SmsConfig
 * @Description TODO
 * @Author 华达州
 * @Date 2021/8/6 13:58
 * @Version 1.0
 **/
@Data
@Component
@ConfigurationProperties(prefix = "smsconfig")
public class SmsConfigProperties {

    private int appId;

    private String appKey;

    private int templateId;

    private String smsSign;

    private int invalidTime;

}

三、集成Redis工具类
/**
 * @ClassName RedisUtil
 * @Description TODO
 * @Author 华达州
 * @Date 2021/8/6 13:54
 * @Version 1.0
 **/
@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * @param key
     * @return 获得值
     * redis有五种数据类型 opsForValue表示是操作字符串类型
     */
    public Object get(String key){
        return  key == null ? null : redisTemplate.opsForValue().get(key);
    }


    /**
     *  本来只可以放入string类型,但是我们配置了自动序列化所以这儿可以传入object
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key,Object value){
        try{
            redisTemplate.opsForValue().set(key,value);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * 原子操作
     * @param key
     * @param value
     * @param expire 过期时间 秒
     * @return
     */
    public boolean setex(String key,Object value,long expire){
        try{
            //TimeUnit.SECONDS指定类型为秒
            redisTemplate.opsForValue().set(key,value,expire, TimeUnit.SECONDS);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * 非原子操作
     * @param key
     * @param expire
     * @return
     */
    public boolean expire(String key,long expire){
        try{
            //这儿没有ops什么的是因为每种数据类型都能设置过期时间
            redisTemplate.expire(key,expire,TimeUnit.SECONDS);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     *
     * @param key
     * @return 获取key的过期时间
     */
    public long ttl(String key){
        return redisTemplate.getExpire(key);
    }

    /**
     *
     * @param keys 删除key 可变参数
     */
    public void del(String ...keys){
        if(keys!=null&&keys.length>0) {
            redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(keys));
        }
    }

    /**
     *
     * @param key
     * @param step  传入正数 就是加多少 传入负数就是减多少
     * @return
     */
    public long incrBy(String key,long step){
        return redisTemplate.opsForValue().increment(key,step);
    }

    /**
     *
     * @param key
     * @param value
     * @return  如果该key存在就返回false 设置不成功 key不存在就返回ture设置成功
     */
    public boolean setnx(String key,Object value){
        return redisTemplate.opsForValue().setIfAbsent(key,value);
    }

    /**
     *  原子操作
     * @param key
     * @param value
     * @param expire  在上面方法加上过期时间设置
     * @return
     */
    public boolean setnxAndExpire(String key,Object value,long expire){
        return redisTemplate.opsForValue().setIfAbsent(key,value,expire,TimeUnit.SECONDS);
    }

    /**
     *
     * @param key
     * @param value
     * @return  如果该key存在就返回之前的value  不存在就返回null
     */
    public Object getAndSet(String key,Object value){
        return redisTemplate.opsForValue().getAndSet(key,value);
    }

    /**
     *
     * @param key
     * @return 判断key是否存在
     */
    public boolean hasKey(String key){
        return redisTemplate.hasKey(key);
    }

四、写Controller接口
@Controller
public class SendMsgController {

    @Autowired
    private UserService userService;

    @Autowired
    private SendSmsUtil sendSmsUtil;

    @Autowired
    private RedisUtil redisUtil;


    /**
     * 发送验证码
     * @author 华达州
     * @date 2021/8/6 21:35
     * @param phone 
     * @return java.lang.String
     */
    @PostMapping("sendCode")
    @ResponseBody
    public String sendCode(@RequestParam String phone){
        return sendSmsUtil.sendSms(phone);
    }


    /**
     * 使用手机号验证码登录
     * @author 华达州
     * @date 2021/8/6 20:26
     * @return java.lang.String
     */
    @PostMapping("codeLogin")  //腾讯云API推荐使用post请求
    @ResponseBody
    public String codeLogin(@RequestParam("phone") String phone,@RequestParam("code")String code){
        User user = userService.getOne(new QueryWrapper<User>().lambda().eq(User::getPhone, phone));
        if(user==null){
            return "用户不存在";
        }
        String oldCode = (String) redisUtil.get(phone);
        if(!code.equals(oldCode)){
            return "验证码错误";
        }
        return "登录成功";
    }

}

上面有两个接口
第一个接口是前端页面点击发送验证码访问的接口,之后用户就会在手机端收到短信验证码
第二个接口是填写验证码之后点击登录访问的接口,访问逻辑和我们开头说的一样,这里不再赘述

这里我就不写前端页面进行测试了
五、直接使用postman进行测试

1、先测试发送验证码
在这里插入图片描述
之后在手机端收到如下短信
在这里插入图片描述

2、接着测试登录接口(五分钟之内)
在这里插入图片描述
可以看到返回登录成功的消息
注意:这里返回登录需要在后台保存了该用户的信息,否则会返回用户不存在,这个就留着你们自己测试吧!!

由于上面只展示了部分代码,想要源码的在这里:https://gitee.com/huadazhou/send-msg.git

拿走记得点个关注

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是Spring Boot Redis验证登录功能的基本步骤: 1. 首先在Spring Boot项目中添加依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> ``` 2. 创建一个Redis配置类,并配置Redis连接息: ```java @Configuration public class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379)); } @Bean public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } } ``` 3. 创建一个用户实体类,并添加相应的字段: ```java @Data @AllArgsConstructor @NoArgsConstructor public class User { private String username; private String password; private String email; private String verificationCode; } ``` 4. 创建一个验证登录控制器,并在其中添加验证码生成和校验逻辑: ```java @RestController public class VerificationCodeLoginController { private final RedisTemplate<String, Object> redisTemplate; public VerificationCodeLoginController(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } @PostMapping("/login") public String login(@RequestParam String username, @RequestParam String password, @RequestParam String verificationCode) { User user = new User(username, password, null, verificationCode); Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<User>> violations = validator.validate(user); if (!violations.isEmpty()) { return "Invalid user information."; } // Get the verification code from Redis. String key = "verification_code:" + username; String storedVerificationCode = (String) redisTemplate.opsForValue().get(key); if (storedVerificationCode == null || !storedVerificationCode.equals(verificationCode)) { return "Invalid verification code."; } // Remove the verification code from Redis. redisTemplate.delete(key); // Log the user in. // ... return "Login successful."; } @GetMapping("/verification-code") public String getVerificationCode(@RequestParam String username) { // Generate a random verification code. String verificationCode = RandomStringUtils.randomNumeric(6); // Save the verification code to Redis. String key = "verification_code:" + username; redisTemplate.opsForValue().set(key, verificationCode, 5, TimeUnit.MINUTES); // Return the verification code. return verificationCode; } } ``` 在以上代码中,`login()`方法用于校验用户名、密码和验证码,并根据校验结果执行登录逻辑。在校验过程中,它首先从Redis中获取该用户的验证码,并与传入的验证码进行比较。如果两者不一致,则返回“Invalid verification code.”,否则从Redis中删除验证码,并执行登录逻辑。`getVerificationCode()`方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华达州

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值