需求
用户在2分钟内,仅允许输入错误密码5次。如果超过次数,限制其登录1小时。(12306)
登录错误次数key: user:loginCount:fail:用户名
锁定限制登录key: user: loginTime: lock:用户名
执行登录功能时:
|1判断当前登录的用户是否被限制登录
1.1如果没有被限制(执行登录功能)
2如果登录成功
2.1登录成功–》(清除输入密码错误次数信 息)
2.2登录不成功
3记录登录错误次数
(判断Redis中的登录次数KEY是否存在) user : loginCount:fail:用户名
3.1如果不存在
是第一次登录失败次数为1
user : loginCount:fail:用户名进行赋值,同时设置失效期
3.2如果存在查询登录失败次数的key结果
if(结果<4)user: loginCount:fail:+1
else{//4限制登录KEY存在,同时设置限制登录时间
实体类
/**
* @author AnQi
* @date 2020/3/13 21 21:56
* @description
*/
public class User implements Serializable {
private static final long serialVersionUID = -8521175777910601162L;
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
//是否被锁的key
public static String getLoginTimeLockKey(String username){
return "user:loginTime:lock:"+username;
}
//登录失败次数key
public static String getLoginCountFailKey(String username){
return "user:loginCount:fail:"+username;
}
public static String getKeyName(){
return "user:";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
redis配置文件同07
.。。。。
service层
/**
* @author AnQi
* @date 2020/3/13 23 45:48
* @description
*/
@Service
public interface UserService {
/**
* STRING 存取 测试
*/
public String getString(String key);
public User login(String uname,String upass);
//登录前的校验
/**
*
* @param uname
* @return
*/
//详细信息
public String loginValdate(String uname);
//是否被 限制登录
public Map<String,Object> loginUserLock(String uname);
}
实现类
/**
* @author AnQi
* @date 2020/3/13 23 47:05
* @description
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
RedisTemplate<String,String> redisTemplate;
/**
* 通过某个key获取值
* 若key不存在 则 再数据库中查询
* 存在 则再redis中查询
* @param key
* @return
*/
public String getString(String key) {
ValueOperations<String, String> vo = redisTemplate.opsForValue();
// redisTemplate.expire("javatest",2, TimeUnit.HOURS);
// redisTemplate.opsForValue().set("javatest2","你出不出来?就问你?",2,TimeUnit.HOURS);
if(redisTemplate.hasKey(key)){
//redis取
System.out.println("redis取");
return vo.get(key);
}else{
//db
String result = "Redis模板练习";
vo.set(key,result);
System.out.println("数据库返回"+result);
return result;
}
}
/**
* 判断是否被限制
* 查询key是否存在
* 存在:被限制 提示 ttl
* 不存在: 不被限制
* @param uname
* @return
*/
@Override
public Map<String , Object> loginUserLock(String uname) {
String key = User.getLoginTimeLockKey(uname);
Map<String , Object> map = new HashMap<>();
if(redisTemplate.hasKey(key)){
//如果存在
Long lockTime = redisTemplate.getExpire(key, TimeUnit.MINUTES);
map.put("flag",true);
map.put("lockTime",lockTime);//剩余时间
}else{
map.put("flag",false);
}
return map;
}
@Override
public User login(String name, String password) {
return null;
}
//登录不成功操作
@Override
public String loginValdate(String uname) {
String key = User.getLoginCountFailKey(uname);
//记录登录次数
int num = 5;//登录错误的次数
if(!redisTemplate.hasKey(key)){
//redistemplate 不能直接赋值 并且设置有效期
//不存在 根据名字设置一个key 并且 设置为1
redisTemplate.opsForValue().set(key,"1");
//设置有效期 2分钟
redisTemplate.expire(key,2,TimeUnit.MINUTES);
return "密码错误! 登录失败,2分钟内,还可以登录 " + (num-1)+ "次!";
}else{
//存在
Long loginCountTime = Long.parseLong(redisTemplate.opsForValue().get(key));
if(loginCountTime<(num-1)){//代表登录次数 小于 4 还有机会
redisTemplate.opsForValue().increment(key,1);//对指定的key 增加1操作
Long time = redisTemplate.getExpire(key,TimeUnit.SECONDS);//剩余时间
return "密码错误! 登录失败,"+time+"秒内,还可以登录 " + (num-loginCountTime-1)+ "次!";
}else{//超过次数了 老哥
//
redisTemplate.opsForValue().set(User.getLoginTimeLockKey(uname),"1");
redisTemplate.expire(User.getLoginTimeLockKey(uname),1,TimeUnit.HOURS);
return "次数超过5次 别Tm登了! 一个小时后见";
}
}
}
}