好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

springboot整合shiro登录失败次数限制功能的实现代码

这次讲讲如何限制用户登录尝试次数,防止坏人多次尝试,恶意暴力破解密码的情况出现,要限制用户登录尝试次数,必然要对用户名密码验证失败做记录,shiro中用户名密码的验证交给了credentialsmatcher 所以在credentialsmatcher里面检查,记录登录次数是最简单的做法。当登录失败次数达到限制,修改数据库中的状态字段,并返回前台错误信息。
 因为之前的博客都是用的明文,这里就不对密码进行加密了,如果有需要加密,将自定义密码比较器从simplecredentialsmatcher改为hashedcredentialsmatcher 然后将对应的配置项打开就可以。

说在前面

非常抱歉,因为我之前整合的时候,只是注意功能,而没有注意细节,导致在登录失败之后,再次转发到 post方法/login 也就是真正的登录方法,导致 再次登录,然后导致下面密码错误3次之后 就 锁定 我设置的是5次.
所以将shiroconfig中的值改为shirofilterfactorybean.setloginurl("/");具体参考源代码。

 另外 还需要将 自定义shirorealm 中 密码对比注销掉, 将密码对比 交给 底层的 密码比较器才可以 锁定用户,否则将 永远报密码错误。,具体代码 如下:

 

 修改登录方法改为登录之后,重定向到/index

限制登录次数

自定义retrylimithashedcredentialsmatcher继承simplecredentialsmatcher

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

package com.springboot.test.shiro.config.shiro;

import java.util.concurrent.atomic.atomicinteger;

import com.springboot.test.shiro.modules.user.dao.usermapper;

import com.springboot.test.shiro.modules.user.dao.entity.user;

import org.apache.log4j.logger;

import org.apache.shiro.authc.authenticationinfo;

import org.apache.shiro.authc.authenticationtoken;

import org.apache.shiro.authc.lockedaccountexception;

import org.apache.shiro.authc.credential.simplecredentialsmatcher;

import org.apache.shiro.cache.cache;

import org.apache.shiro.cache.cachemanager;

import org.springframework.beans.factory.annotation.autowired;

/**

  * @author: wangsaichao

  * @date: 2018/5/25

  * @description: 登陆次数限制

  */

public class retrylimithashedcredentialsmatcher extends simplecredentialsmatcher {

  private static final logger logger = logger.getlogger(retrylimithashedcredentialsmatcher. class );

  @autowired

  private usermapper usermapper;

  private cache<string, atomicinteger> passwordretrycache;

  public retrylimithashedcredentialsmatcher(cachemanager cachemanager) {

   passwordretrycache = cachemanager.getcache( "passwordretrycache" );

  }

  @override

  public boolean docredentialsmatch(authenticationtoken token, authenticationinfo info) {

   //获取用户名

   string username = (string)token.getprincipal();

   //获取用户登录次数

   atomicinteger retrycount = passwordretrycache.get(username);

   if (retrycount == null ) {

    //如果用户没有登陆过,登陆次数加1 并放入缓存

    retrycount = new atomicinteger( 0 );

    passwordretrycache.put(username, retrycount);

   }

   if (retrycount.incrementandget() > 5 ) {

    //如果用户登陆失败次数大于5次 抛出锁定用户异常 并修改数据库字段

    user user = usermapper.findbyusername(username);

    if (user != null && "0" .equals(user.getstate())){

     //数据库字段 默认为 0 就是正常状态 所以 要改为1

     //修改数据库的状态字段为锁定

     user.setstate( "1" );

     usermapper.update(user);

    }

    logger.info( "锁定用户" + user.getusername());

    //抛出用户锁定异常

    throw new lockedaccountexception();

   }

   //判断用户账号和密码是否正确

   boolean matches = super .docredentialsmatch(token, info);

   if (matches) {

    //如果正确,从缓存中将用户登录计数 清除

    passwordretrycache.remove(username);

   }

   return matches;

  }

  /**

   * 根据用户名 解锁用户

   * @param username

   * @return

   */

  public void unlockaccount(string username){

   user user = usermapper.findbyusername(username);

   if (user != null ){

    //修改数据库的状态字段为锁定

    user.setstate( "0" );

    usermapper.update(user);

    passwordretrycache.remove(username);

   }

  }

}

在shiroconfig中配置该bean

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/**

  * 配置密码比较器

  * @return

  */

@bean ( "credentialsmatcher" )

public retrylimithashedcredentialsmatcher retrylimithashedcredentialsmatcher(){

  retrylimithashedcredentialsmatcher retrylimithashedcredentialsmatcher = new retrylimithashedcredentialsmatcher(ehcachemanager());

 

  //如果密码加密,可以打开下面配置

  //加密算法的名称

  //retrylimithashedcredentialsmatcher.sethashalgorithmname("md5");

  //配置加密的次数

  //retrylimithashedcredentialsmatcher.sethashiterations(1024);

  //是否存储为16进制

  //retrylimithashedcredentialsmatcher.setstoredcredentialshexencoded(true);

 

  return retrylimithashedcredentialsmatcher;

}

在shirorealm中配置密码比较器

?

1

2

3

4

5

6

7

8

9

10

11

12

/**

  * 身份认证realm; (这个需要自己写,账号密码校验;权限等)

  * @return

  */

@bean

public shirorealm shirorealm(){

  shirorealm shirorealm = new shirorealm();

  ......

  //配置自定义密码比较器

  shirorealm.setcredentialsmatcher(retrylimithashedcredentialsmatcher());

  return shirorealm;

}

在ehcache-shiro.xml添加缓存项

?

1

2

3

4

5

6

7

8

9

10

11

12

<!-- 登录失败次数缓存

   注意 timetoliveseconds 设置为 300 秒 也就是 5 分钟

   可以根据自己的需求更改

  -->

<cache name= "passwordretrycache"

   maxentrieslocalheap= "2000"

   eternal= "false"

   timetoidleseconds= "0"

   timetoliveseconds= "300"

   overflowtodisk= "false"

   statistics= "true" >

</cache>

在logincontroller中添加解除admin用户限制方法

?

1

2

3

4

5

6

7

8

9

10

11

12

13

/**

  * 解除admin 用户的限制登录

  * 写死的 方便测试

  * @return

  */

@requestmapping ( "/unlockaccount" )

public string unlockaccount(model model){

  model.addattribute( "msg" , "用户解锁成功" );

 

  retrylimithashedcredentialsmatcher.unlockaccount( "admin" );

 

  return "login" ;

}

注意:为了方便测试,记得将 unlockaccount 权限改为 任何人可访问。

在login.html页面 添加 解锁admin用户的按钮

?

1

<a href= "/unlockaccount" rel= "external nofollow" >解锁admin用户</a></button>

测试结果

 


总结

以上所述是小编给大家介绍的springboot整合shiro-登录失败次数限制,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

原文链接:https://blog.csdn.net/qq_34021712/article/details/80461177

查看更多关于springboot整合shiro登录失败次数限制功能的实现代码的详细内容...

  阅读:80次