redis(5)

news2025/2/27 5:45:00

需求:防止用户进行暴力破解密码

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Controller
public class UserController {
    @Autowired
    private StringRedisTemplate template;

    @RequestMapping("/login")
    @ResponseBody
    public String start(String username, String password){
        String key="user:logincount:"+username;
        String lockKey="user:lock:"+username;
        if(template.hasKey(lockKey)){
            return "您的账户已经被锁死,请在"+template.getExpire(lockKey)+"秒后进行操作";
        }else {
            if (username.equals("admin") && password.equals("admin")) {
                return "登陆成功";
            } else {
                if (!template.hasKey(key)) {
                    int value = 1;
                    template.opsForValue().set(key, String.valueOf(value), 120, TimeUnit.SECONDS);
                } else {
                    template.opsForValue().increment(key);
                }
                if (Integer.parseInt(template.opsForValue().get(key)) > 5) {
                    template.opsForValue().set(lockKey, "该账户被锁死", 10000, TimeUnit.SECONDS);
                    return "您在2min内登录超过5次失败,您的帐户将被锁死10000s";
                }
                return "登陆失败";
            }
        }
    }

}

 一)发送短信验证码

1)校验手机号是否符合正确的格式

2)校验成功生成验证码

3)保存验证码到session里面

4)发送验证码

二)短信验证码进行登陆注册

1)校验手机号和验证码是否符合正确的格式,如果不符合直接返回错误信息

2)从session中获取到手机号的验证码比对和用户客户端提交过来的验证码是否一致,如果不一致,直接返回错误信息

3)如果验证码校验成功,那么直接根据用户名来进行查询对应的用户信息,如果查询到了,直接将用户信息保存到session里面,如果用户不存在,那么新创建用户保存到session里面

拓展:在hutu里面的BeanUtil.copyProperties方法是把user对象中的所有属性放到UserDemo的一个同名属性里面,并返回UserDemo对象

UserDemo Demo=BeanUtil.copyProperties(user,UserDemo.class);
@Controller
public class UserController {
    @Autowired
    private StringRedisTemplate template;

    @RequestMapping("/getCode")
    @ResponseBody
    public String GetCode (String TelephoneNumber, HttpSession session){
        if(!StringUtils.hasLength(TelephoneNumber)){
            return "前端输入的手机号为空";
        }
        String code= RandomUtil.randomNumbers(6);
        System.out.println(code);
        session.setAttribute("UserCode",code);
        return "发送验证码成功";
    }
    @RequestMapping("/login")
    @ResponseBody
    public String login(String TelephoneNumber,HttpSession session,String UserCode){
        //1.校验手机号和验证码
        if(!StringUtils.hasLength(TelephoneNumber)){
            return "前端输入的手机号为空";
        }
        String code= (String) session.getAttribute("UserCode");
        if((code==null||code.equals(""))){
            return "您之前没有发送过验证码";
        }
        if(!code.equals(UserCode)){
            return "您输入验证码错误";
        }
        //2.从数据库查询用户信息 select * from user where TelephoneNumber=XXXX
        session.removeAttribute("UserCode");
        User user=new User();
        user.setUserID(1);
        user.setUsername("张三");
        user.setPassword("李四");
        user.setClassID(10);
        session.setAttribute("user",user);
        return "登陆成功";
    }

}

多个session共享的问题:多台Tomact并不是共享session空间的,当请求切换到不同的Tomact服务的时候会出现不同的问题

1)数据共享

2)内存存储,提高读写效率

3)key-value键值对

使用redis来发送验证码

1)验证码保存:因为redis是多台服务器共享的,因为我们要把验证码信息保存在Session里面,但是一定要保证每一名用户所进行发送的验证码保存在redis中的key必须是不一样的,不能使用固定的名称key作为键值对的键,否则拿到大家都是用同一个验证码吗?

key:"user:TelephoneNumber:"+TelephoneNumber

key="user:TemphoneNumber:1367878",value="9090"

2)用户信息保存:因为hash结构可以将对象的每一个单独字段进行保存,并且可以针对单个字段做CRUD

 

还要注意一下,当我们进行登陆之后,要向redis中进行存储用户的有效信息,那么必须必须设定过期时间,但是这个过期时间和普通的session又是略有不同

1)session的过期时间:只要超过用户30min不进行访问业务,那么session中的信息就会被销毁,如果用户一直访问Session,那么有效期就是一直是30min

2)但是上面我们使用redis来进行存储用户的登录信息,无论用户是否在进行操作业务逻辑,那么最终redis都会在30min之内进行销毁redis

所以解决方案就是只要用户进行访问我们的业务,我们就需要重新设置用户的信息在redis中的有效期为30min,也就是说是否触发了拦截器,如果不触发拦截器,那么就直接在30min钟内将redis中的用户信息删除

package com.example.demo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class UserController {
    @Autowired
    private StringRedisTemplate template;

    @RequestMapping("/getCode")
    @ResponseBody
    public String GetCode (String TelephoneNumber, HttpSession session){
        if(!StringUtils.hasLength(TelephoneNumber)){
            return "前端输入的手机号为空";
        }
        String code= RandomUtil.randomNumbers(6);
        System.out.println(code);
       //生成key,保证每一个人的redis的key都不一样
        String key="user:TelephoneNumber:"+TelephoneNumber;
        template.opsForValue().set(key,code,30, TimeUnit.MINUTES);
        return "发送验证码成功";
    }
    @RequestMapping("/login")
    @ResponseBody
    public String login(String TelephoneNumber,HttpSession session,String UserCode){
        //1.校验手机号和验证码
        if(!StringUtils.hasLength(TelephoneNumber)){
            return "前端输入的手机号为空";
        }
       String key="user:TelephoneNumber:"+TelephoneNumber;
        String code=template.opsForValue().get(key);
        if((code==null||code.equals(""))){
            return "您之前没有发送过验证码";
        }
        if(!code.equals(UserCode)){
            return "您输入验证码错误";
        }
        //2.从数据库查询用户信息 select * from user where TelephoneNumber=XXXX
        User user=new User();
        user.setUserID(1);
        user.setUsername("张三");
        user.setPassword("李四");
        user.setClassID(10);
        //2.1.生成一个token作为令牌,并作为存储在redis中的key
        String token= "loginUser:token"+UUID.randomUUID();
        //2.2.把User对象转化成Hash格式来进行存储
        HashMap<String,String> result=new HashMap<>();
        result.put("userID",user.getUserID()+"");
        result.put("username", user.getUsername());
        result.put("password", user.getPassword());
        result.put("classID",user.getClassID()+"");
        template.opsForHash().putAll(token,result);
        template.expire(token,30,TimeUnit.MINUTES);
        //2.3.向客户端返回token
        return "登陆成功"+token;
    }

}
@Controller
public class UserController {
    @Autowired
    private StringRedisTemplate template;

    @RequestMapping("/getCode")
    @ResponseBody
    public String GetCode (String TelephoneNumber, HttpSession session){
        if(!StringUtils.hasLength(TelephoneNumber)){
            return "前端输入的手机号为空";
        }
        String code= RandomUtil.randomNumbers(6);
        System.out.println(code);
        //生成key,保证每一个人的redis的key都不一样
        String key="user:TelephoneNumber:"+TelephoneNumber;
        template.opsForValue().set(key,code,30, TimeUnit.MINUTES);
        return "发送验证码成功";
    }
    @RequestMapping("/login")
    @ResponseBody
    public String login(String TelephoneNumber,HttpSession session,String UserCode){
        //1.校验手机号和验证码
        if(!StringUtils.hasLength(TelephoneNumber)){
            return "前端输入的手机号为空";
        }
        String key="user:TelephoneNumber:"+TelephoneNumber;
        String code=template.opsForValue().get(key);
        if((code==null||code.equals(""))){
            return "您之前没有发送过验证码";
        }
        if(!code.equals(UserCode)){
            return "您输入验证码错误";
        }
        //2.从数据库查询用户信息 select * from user where TelephoneNumber=XXXX
        User user=new User();
        user.setUserID(1);
        user.setUsername("张三");
        user.setPassword("李四");
        user.setClassID(10);
        //2.1.生成一个token作为令牌,并作为存储在redis中的key
        String token= "loginUser:token"+UUID.randomUUID();
        //2.2.把User对象转化成Hash格式来进行存储
        HashMap<String,String> result=new HashMap<>();
        result.put("userID",user.getUserID()+"");
        result.put("username", user.getUsername());
        result.put("password", user.getPassword());
        result.put("classID",user.getClassID()+"");
        template.opsForHash().putAll(token,result);
        template.expire(token,30,TimeUnit.MINUTES);
        //2.3.向客户端返回token
        return "登陆成功"+token;
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/501012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构-树、森林应用(哈夫曼树)

目录 一、树存储结构 1.1双亲表示法 1.2孩子表示法 *1.3孩子兄弟表示法 * 二、树&#xff0c;森林、二叉树之间的转化 三、树和森林的遍历 3.1树 *3.1.1先根遍历 *3.1.2后根遍历 *3.1.3层次遍历 3.2森林 * 3.2.1先序遍历 *3.2.2中序遍历 *等同关系 四、哈夫曼树和哈夫…

开源音频处理库AudioLDM

环境 windows 10 64bitAudioLDM 0.1.1anaconda with python 3.8nvidia gtx 1070Ti 简介 AudioLDM 是一个开源的音频处理库&#xff0c;它可以用于实现语音识别、语音合成、语音转换等应用&#xff0c;很多 AIGC 大模型都在用它。该库提供了一组音频信号处理算法&#xff0c;包括…

shell脚本知识汇聚之地

shell脚本 shell脚本shell脚本编写变量的定义变量的使用变量值调换引号的使用环境变量输出全局变量只读变量位置变量预定义变量条件判断操作if语句case语句for语句while语句until语句退出循环sleep循环等待时间shift 去除第一个位置变量参数${} $变量的特殊显示方式echo用法 sh…

el-cascader后台给一组id回显可选择的选项列表

根据后台给一组id回显可选择的选项列表 <template><div><el-cascader:key"keyValue"ref"cascader"v-model"pids":props"{ label: name, value: id }":options"options"clearablefilterablechange"handl…

Maven配置阿里云仓库https

2022年开始&#xff0c;阿里云对以前的maven仓库地址进行升级&#xff0c;由原来的http换成https 原来链接&#xff1a; http://maven.aliyun.com/repository/public 现在链接&#xff1a; https://maven.aliyun.com/repository/public maven settings.xml配置 maven settin…

QString的解析与常用功能

QString存储一个16位QChar字符串&#xff0c;其中每个QChar对应一个UTF-16代码单元。(编码值大于65535的Unicode字符使用代理对存储&#xff0c;即两个连续的qchar。) Unicode是一个国际标准&#xff0c;支持目前使用的大多数书写系统。它是US-ASCII (ANSI X3.4-1986)和Latin-1…

盐湖卤水中分离硼的工艺有哪些

锂因其优良的物理化学性质&#xff0c;被认为是“推动世界进步的能源金属”&#xff0c;随着新能源、冶金等行业的快速发展&#xff0c;人们对锂的需求量逐年攀升。然而地壳中锂的含量仅为0.0065%左右&#xff0c;约80%的锂资源蕴含于盐湖卤水中。 盐湖卤水成分复杂&#xff0c…

Redis入门到入土(day03)

Redis的持久化 Redis 是内存数据库&#xff0c;如果不将内存中的数据库状态保存到磁盘&#xff0c;那么一旦服务器进程退出&#xff0c;服务器中的数据库状态也会消失。所以 Redis 提供了持久化功能&#xff01; RDB&#xff08;Redis DataBase&#xff09; 什么是RDB 在指…

HugNLP发布,集成多种NLP任务,可训ChatGPT类模型

HugNLP发布&#xff0c;集成多种NLP任务&#xff0c;可训ChatGPT类模型 作者&#xff1a;王嘉宁 HugNLP——全面统一的NLP框架开源了&#xff01; 近日&#xff0c;华师大HugAILab团队研发了HugNLP框架&#xff0c;这是一个面向研究者和开发者的全面统一的NLP训练框架&#x…

java版企业电子招投标采购系统源代码之系统的首页设计

​​ 功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为…

来来来,一起了解下MTK(联发科)

​ https://www.mediatek.com/ ​ 进入MTK官网&#xff0c;可以看到其产品分为七大方向&#xff1a;智能手机、笔记本电脑与平板电脑、家庭娱乐、车用市场、连接与网络技术、定制芯片服务、物联网。这里主要介绍智能手机、连接与网络技术、物联网三大版块。 一、智能手机 智…

使用护眼灯台灯哪个牌子好用来保护眼睛?真正做到护眼台灯品牌

现在的家长很多人觉得家里已经有灯光了&#xff0c;没必要在买台灯。但事实上台灯有很多优点&#xff0c;尤其对于小孩子来说&#xff1a;1.提供更好的光线:台灯能够提供更加明亮的光线&#xff0c;有助于保护眼睛健康。2.提高工作效率:台灯光线舒适可提高工作效率或学习效率。…

STM32G0开发板下载代码问题

任务&#xff1a; 通过CueMX生成代码&#xff0c;然后烧写到STM32G0开发板上。 遇到的问题&#xff1a; 1. CubeMX生成的代码能用Keil编译&#xff0c;但是下载不到flash中 2. CubeMX再次生成代码后&#xff0c;SWD无法识别芯片。 逐个击破&#xff1a; 1. CubeMX生成的代码…

Axure教程:动态分组柱状图(中继器)

本文将教大家如何用AXURE中的中继器做组分组柱状图。 如图&#xff1a; 预览地址&#xff1a;https://vvpq8c.axshare.com 原型下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87761575?spm1001.2014.3001.5503 一、功能介绍 1、在中继器或表格中填…

php导出excel多个sheet

我引用的拓展是&#xff1a; "phpoffice/phpspreadsheet": "^1.4", 我的$accept数据是这样的 "data": { "examStu": [ { "ctime": "2023-04-27 16:28:16", "className": "大猛1", "n…

JavaScript—数据类型转换

目录 1、起 源 理 念 2、特 点 框 架 书 写 位 置 注 释 浏览器调试js代码 3、变量 ① 全局变量 ② 局部变量 ③ 常量 4、数据类型 严格检查数据类型-use strict ① 数 组 ② 字符串 6、类型转换 ① 字符串转数字 ② 字符串转bool值 ③ 能力判断 7、编码方…

自动控制原理笔记-频率响应法-稳定裕度

目录 一、增益裕度h&#xff08;幅值裕度, gain margin&#xff09; 二、相角裕度g (phase margin) 三、根据Bode图确定稳定裕度 相角裕度 一、增益裕度h&#xff08;幅值裕度, gain margin&#xff09; 开环幅相特性曲线&#xff08;奈氏曲线&#xff09;G(jw)与负实轴…

教你一招在VMware的NAT模式下,两台电脑如何互相访问对方的虚拟机

目录 一. 准备工作二. 开始2.1 设置NAT模式2.2 进行NAT模式设置2.3 XShell访问对方虚拟机 一. 准备工作 需要两台电脑&#xff08;我准备了两台win10&#xff09; VMware虚拟机&#xff1a;【官网下载】两台win10电脑上都安装好centos 7系统&#xff08;我这里是centos 7版本…

3.Java线程

Java线程 3.1 创建和运行线程 方法一&#xff0c;直接使用Thread import lombok.extern.slf4j.Slf4j;/*** 使用匿名内部类创建线程* author xc* date 2023/4/30 16:19*/ Slf4j public class Test1 {public static void main(String[] args) {Thread thread new Thread(){Ov…

OpenCV-Python图像几何变换

概念&#xff1a;几何变换是指将一幅图像映射到另外一幅图像内的操作。OpenCV提供了多个与映射有关的函数&#xff0c;这些函数使用起来方便灵活&#xff0c;能够高效地完成图像的映射。 缩放 cv2.resize()函数用于缩放图像 det cv2.resize(src, dsize[,dst[,fx[,fy[,interp…