使用Ehcache缓存在用户输错n次账户密码之后冻结m小时的简单实现

我们经常会看到有些系统,为了提高账户安全性,会在用户输入n次密码时候锁定对应的账户一段时间,这样可以避免暴力破解用户密码(说实话这样行不行我也不知道)。不知道正确的实现姿势应该是什么样的,但是我们可以利用缓存来简单实现这个功能,先来一盘代码:

0、初始化配置

为每个用户初始化保存到缓存中的key

    private int MAX_FAIL_TIMES = 3;// 默认最多允许出错次数
	private int FROZEN_TIME = 1;// 默认冻结时间,单位[小时]
	private String COUNT_KEY;// 失败次数缓存Key
	private String TIME_KEY;// 冻结时间缓存Key
	private long USERID;// 冻结的用户ID

	private String CACHE_REGION = "Account";

	public static FrozenAccountTool init(String key, long userId, int maxFailTimes, int frozenTime) {

		FrozenAccountTool frozenAccountTool = new FrozenAccountTool();

		frozenAccountTool.USERID = userId;
		frozenAccountTool.COUNT_KEY = key + "#USER#COUNT#" + frozenAccountTool.USERID;
		frozenAccountTool.TIME_KEY = key + "#USER#TIME#" + frozenAccountTool.USERID;
		frozenAccountTool.MAX_FAIL_TIMES = maxFailTimes > 0 ? maxFailTimes : frozenAccountTool.MAX_FAIL_TIMES;
		frozenAccountTool.FROZEN_TIME = frozenTime > 0 ? frozenTime : frozenAccountTool.FROZEN_TIME;
		return frozenAccountTool;
	}

1、记录验证失败次数

首先需要记录用户输错的次数,每次验证失败的时候,失败次数+1

    // 失败次数+1
	public void failCountIncrease() {
		int failCount = GetFailCount();
		_SetFailCount(failCount + 1);
	}

GetFailCount() 方法用于从缓存里面取出当前失败的次数,具体实现如下:

        // 获取失败次数
	public int GetFailCount() {
		return EhcacheUtil.get(CACHE_REGION, COUNT_KEY) == null ? 1 : (Integer) EhcacheUtil.get(CACHE_REGION, COUNT_KEY);
	}

再看一下 _SetFailCount() 方法,这里是为了在失败次数大于最大失败次数的时候设置当前时间为锁定时间,用于后面判断解锁时间是否已经到了:

        // 設置失败次数
	private void _SetFailCount(int failCount) {
		EhcacheUtil.put(CACHE_REGION, COUNT_KEY, failCount);
		if (failCount >= MAX_FAIL_TIMES) {
			SetFrozenTime();
		}
	}

2、判断账户是否被冻结

<1>.首先判断当前时间点距离被锁定的时间是否大于设定锁定的时间,大于表示已经解锁,重置锁定设置的缓存数据;注:这个要先判断,要不然锁定之后就永远无法解锁了

<2>.如果时间还没到设定锁定的时间则判断当前失败次数是否大于最大失败次数,大于表示已经被锁定

public boolean IsFrozen() {
		long frozenTimeMillis = GetFrozenTime();
		System.out.println(new Date() + ">锁定时间:" + GetFrozenTime());
		System.out.println(new Date() + ">当前错误次数:" + GetFailCount());
		if (frozenTimeMillis > 0 && (System.currentTimeMillis() - frozenTimeMillis > FROZEN_TIME * 60 * 60 * 1000)) {
			System.out.println(new Date() + ">锁定时间到,解锁账号");
			resetFrozen();
			return false;
		} else if (GetFailCount() >= MAX_FAIL_TIMES) {
			System.out.println(new Date() + ">账号已锁定..");
			return true;
		}
		System.out.println(new Date() + ">账号未锁定..");
		return false;
	}

温馨提示:以上的方法命名不符合java规范,大写是为了避免get、set、is开头的方法和javabean规范的冲突,仅供参考

** 3、如何使用 **

输入图片说明

4、测试代码

        FrozenAccountTool frozenAccountTool1 = FrozenAccountTool.init("GETCASH", 593115, 5, 1);
		for (int i = 0; i < 5; i++) {
			frozenAccountTool1.failCountIncrease();
			Thread.sleep(2000);
		}
		boolean result = true;
		while (result) {
			result = frozenAccountTool1.IsFrozen();
			Thread.sleep(5000);
		}

5、测试结果 (这里只设置锁定了0.01个小时)

输入图片说明

6、最后

我们可以看到开源中国社区的登陆也是用了同样的原理,用户输错2次密码的时候会出现验证码,输错密码次数大于限定的次数后该email账号会被锁定两个小时

(1)输错两次密码后,万恶的验证码出现了

输入图片说明

(2)输错N次之后

输入图片说明

不相信可以自己去试一下哦,似乎可以做什么坏事的样子

关于Ehcache工具类和其他代码已经托管到:https://git.oschina.net

转载于:https://my.oschina.net/tanweijie/blog/711206

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值