后台添加登陆次数限制(Ruoyi若依前后分离版)

上次添加密文传输后 这次添加了登陆次数限制(后台均可使用此方法和思路)

简单来讲就是 同一用户输入密码错误某次以上 限制登陆一段时间


实现这个功能分为两点

  1. 记录密码错误次数和错误时间
  2. 密码正确后清除错误次数

数据库添加字段

在记录用户信息的表中添加两个字段

错误次数 error_nums int类型 (设置默认为0)

错误时间 error_times varchar类型或datetime类型

添加接口和字段

在你的用户信息(SysUser.java)实体类里添加字段 并生成getset方法

/**
 * 错误次数
 */
private int errorNums;
/**
 * 错误时间
 */
private String errorTimes;

新增两个接口

    /**
     * 增加密码错误次数
     *
     * @param sysUser 用户信息
     * @return 结果
     */
    public int updateErrorNums(SysUser sysUser);

    /**
     * 清空密码错误次数
     *
     * @param username 用户名
     * @return 结果
     */
    public int cleanErrorNums(String username);

我的系统使用的myBatis 所以在xml文件要加上字段 和sql

        
<resultMap type="SysUser" id="SysUserResult">
        ...
        ...
        <result property="errorNums" column="error_nums"/>
        <result property="errorTimes" column="error_times"/>
        ...
</resultMap>


    <!--is null or LENGTH( trim( 字段 ) 判断是否为空 或无值 -->
    <update id="updateErrorNums" parameterType="SysUser">
 		update sys_user
 		set error_nums = if(error_nums is null or LENGTH( trim( error_nums )) = 0, 0, error_nums) + 1,
 		error_times = if(#{errorTimes} is null,now(),#{errorTimes})
 		where user_name = #{userName}
	</update>

    <update id="cleanErrorNums" parameterType="String">
 		update sys_user set error_nums = 0 where user_name = #{userName}
	</update>

查询用户角色的sql也需要加上字段

 if(error_nums is null or LENGTH( trim( error_nums )) = 0, 0, error_nums) + 1

当error_nums为空 或无值时 赋值为0 加1 如有值直接+1

if(#{errorTimes} is null,now(),#{errorTimes})

当参数errorTimes为null 后无值 传当前时间(yyyy-MM-dd HH:mm:ss)格式

注意下系统服务器的时间是否为北京时间 不是 可以用下面设置更改

--mysql
select NOW();
select sysdate();
select localtime();

show variables like '%time_zone%';

set global time_zone = '+8:00';
或
set global time_zone='Asia/Shanghai'

--linux设置时间
date -s "20220527 18:30:50"

添加登陆限制接口

根据大家反应 如想某时间段内错误几次后,限制登陆 需多判断下错误时间

/**
     * 登陆错误限制
     * 更新时sys_user加两字段
     * error_nums int类型(默认0!!)
     * error_times varchar类型
     *
     * @param sysUser
     */
    public void loginError(SysUser sysUser) {
        //能进来代表用户正常 单纯密码错误
        if (sysUser.getErrorNums() > UserStatus.WRONG_TIMES) {
            long timeNow = DateUtils.timeToStampSecond(DateUtils.getTime());
            long errorTimes = DateUtils.timeToStampSecond(sysUser.getErrorTimes()) + UserStatus.WRONG_DURATION * 60;
            if (errorTimes - timeNow > 0) {
                String s = DateUtils.formatHMS(errorTimes - timeNow);
                throw new CustomException("对不起,您的账号:" + sysUser.getUserName() + " 错误次数过多,请" + s + "后重试");
            }
        }
            /**如果想添加某时间段内错误某次后限制
              在第一次密码错误时添加错误时间,再次密码错误时,对比和第一次密码错误的时间
              如在限制时间内 错误次数+1(第一次的错误时间不要覆盖)
              如超过自定义的时间则清除错误时间和错误次数
            */
        if (sysUser.getErrorNums() < UserStatus.WRONG_TIMES) {
            userService.updateErrorNums(sysUser);
            throw new CustomException("还有" + (UserStatus.WRONG_TIMES - sysUser.getErrorNums()) + "次输入机会");
        } else {
            sysUser.setErrorTimes(DateUtils.getTime());
            userService.updateErrorNums(sysUser);
            throw new CustomException("对不起,您的账号:" + sysUser.getUserName() + " 错误次数过多,请" + UserStatus.WRONG_DURATION + "分钟后重试");
        }
    }

timeToStampSecond()是string类型日期转时间戳(秒级)方法

formatHMS() 是long类型时间(秒级)转 天/小时/分钟/秒 大家可以添加下方法

/**
     * String类型日期(2021-12-07 10:00:00)转时间戳(秒级)
     *
     * @param time
     * @return
     */
    public static long timeToStampSecond(String time) {
        Date d = new Date();
        long timeStamp = 0;
        try {
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            d = sf.parse(time);// 日期转换为时间戳
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        timeStamp = d.getTime() / 1000;
        return timeStamp;
    }

/**
     * 秒转天/小时/分钟/秒
     *
     * @param value
     * @return
     */
    public static String formatHMS(long value) {
        String str = "";
        long i = value / (3600 * 24);
        if (i > 0) {
            str = i + "天";
        }
        value %= 3600 * 24;
        i = value / 3600;
        if (i > 0) {
            str += i + "时";
        }
        value %= 3600;
        i = value / 60;
        if (i > 0) {
            str += i + "分";
        }
        value %= 60;
        str += value + "秒";
        return str;
    }

WRONG_TIMES和WRONG_DURATION是我添加的枚举类字段 方便之后更改限制次数和时间

    //密码错误次数
    public static int WRONG_TIMES = 3;
    //密码解锁时长(分钟)
    public static int WRONG_DURATION = 5;

现在接口都已写好 就看在哪里使用了

打开SysLoginService.java

 /**
  *登录验证
  */
public String login(String username, String password, String code, String uuid) {
              .......
              .......

              Authentication authentication = null;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername/decryptByPrivateKey()私钥解密
            authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, RsaUtils.decryptByPrivateKey(password)));
        } catch (Exception e) {
            //进入这里代表密码错误
            if (e instanceof BadCredentialsException) {
                //登陆限制 错误三次限制五分钟
                loginError(userService.selectUserByUserName(username));
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            } else {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new CustomException(e.getMessage());
            }
        }
        //登陆成功后记得清除错误次数
        userService.cleanErrorNums(username);
        ......
        ......
}

验证错误次数的方法 要放在catch中 因为只是在密码误时引用 如果放在try中 会影响UserDetailsServiceImpl中的账号判断

登陆成功后记得清除错误次数 方法要放在try catch后面

 最后大家需要跟具自己代码做调整 有什么问题欢迎留言讨论😋

  • 16
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 41
    评论
好的,我了解了。如果你想去除若依ruoyi)的UI,可以按照以下步骤进行: 1. 进入若依ruoyi)的源代码目录,找到 `ruoyi-ui` 文件夹 2. 用文本编辑器打开 `ruoyi-ui` 文件夹下的 `src` 目录下的 `main.js` 文件 3. 在该文件中删除以下代码块: ```javascript import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) ``` 4. 保存并关闭 `main.js` 文件 5. 打开 `ruoyi-ui` 文件夹下的 `src` 目录下的 `App.vue` 文件 6. 在该文件中删除以下代码块: ```html <template> <div id="app"> <router-view/> </div> </template> <script> export default { name: 'App' } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style> ``` 7. 保存并关闭 `App.vue` 文件 8. 运行 `npm run build` 命令编译打包项目 9. 打开 `ruoyi-ui` 文件夹下的 `dist` 目录,找到生成的 `index.html` 文件 10. 用文本编辑器打开 `index.html` 文件,删除以下代码块: ```html <link href="/static/css/app.8dcf7f7f.css" rel="stylesheet"> <script type="text/javascript" src="/static/js/manifest.1f7d4595.js"></script> <script type="text/javascript" src="/static/js/vendor.7a1b1d27.js"></script> <script type="text/javascript" src="/static/js/app.5b2c8f27.js"></script> ``` 11. 保存并关闭 `index.html` 文件,这样就去除了若依ruoyi)的UI。 请注意,这只是去除了若依ruoyi)的UI,不会影响若依ruoyi)的功能和其他特性。如果你需要使用若依ruoyi)的UI,可以按照以上步骤恢复。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

夜の雨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值