springboot整合shiro登錄失敗次數(shù)限制功能的實(shí)現(xiàn)代碼
這次講講如何限制用戶登錄嘗試次數(shù),防止壞人多次嘗試,惡意暴力破解密碼的情況出現(xiàn),要限制用戶登錄嘗試次數(shù),必然要對(duì)用戶名密碼驗(yàn)證失敗做記錄,Shiro中用戶名密碼的驗(yàn)證交給了CredentialsMatcher 所以在CredentialsMatcher里面檢查,記錄登錄次數(shù)是最簡(jiǎn)單的做法。當(dāng)?shù)卿浭〈螖?shù)達(dá)到限制,修改數(shù)據(jù)庫中的狀態(tài)字段,并返回前臺(tái)錯(cuò)誤信息。
因?yàn)橹暗牟┛投际怯玫拿魑?這里就不對(duì)密碼進(jìn)行加密了,如果有需要加密,將自定義密碼比較器從SimpleCredentialsMatcher改為HashedCredentialsMatcher 然后將對(duì)應(yīng)的配置項(xiàng)打開就可以。
說在前面
非常抱歉,因?yàn)槲抑罢系臅r(shí)候,只是注意功能,而沒有注意細(xì)節(jié),導(dǎo)致在登錄失敗之后,再次轉(zhuǎn)發(fā)到 post方法/login 也就是真正的登錄方法,導(dǎo)致 再次登錄,然后導(dǎo)致下面密碼錯(cuò)誤3次之后 就 鎖定 我設(shè)置的是5次.
所以將shiroConfig中的值改為shiroFilterFactoryBean.setLoginUrl("/");具體參考源代碼。
另外 還需要將 自定義ShiroRealm 中 密碼對(duì)比注銷掉, 將密碼對(duì)比 交給 底層的 密碼比較器才可以 鎖定用戶,否則將 永遠(yuǎn)報(bào)密碼錯(cuò)誤。,具體代碼 如下:
修改登錄方法改為登錄之后,重定向到/index
限制登錄次數(shù)
自定義RetryLimitHashedCredentialsMatcher繼承SimpleCredentialsMatcher
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: 登陸次數(shù)限制 */ 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(); //獲取用戶登錄次數(shù) AtomicInteger retryCount = passwordRetryCache.get(username); if (retryCount == null) { //如果用戶沒有登陸過,登陸次數(shù)加1 并放入緩存 retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if (retryCount.incrementAndGet() > 5) { //如果用戶登陸失敗次數(shù)大于5次 拋出鎖定用戶異常 并修改數(shù)據(jù)庫字段 User user = userMapper.findByUserName(username); if (user != null && "0".equals(user.getState())){ //數(shù)據(jù)庫字段 默認(rèn)為 0 就是正常狀態(tài) 所以 要改為1 //修改數(shù)據(jù)庫的狀態(tài)字段為鎖定 user.setState("1"); userMapper.update(user); } logger.info("鎖定用戶" + user.getUsername()); //拋出用戶鎖定異常 throw new LockedAccountException(); } //判斷用戶賬號(hào)和密碼是否正確 boolean matches = super.doCredentialsMatch(token, info); if (matches) { //如果正確,從緩存中將用戶登錄計(jì)數(shù) 清除 passwordRetryCache.remove(username); } return matches; } /** * 根據(jù)用戶名 解鎖用戶 * @param username * @return */ public void unlockAccount(String username){ User user = userMapper.findByUserName(username); if (user != null){ //修改數(shù)據(jù)庫的狀態(tài)字段為鎖定 user.setState("0"); userMapper.update(user); passwordRetryCache.remove(username); } } }
在shiroConfig中配置該bean
/** * 配置密碼比較器 * @return */ @Bean("credentialsMatcher") public RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher(){ RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher = new RetryLimitHashedCredentialsMatcher(ehCacheManager()); //如果密碼加密,可以打開下面配置 //加密算法的名稱 //retryLimitHashedCredentialsMatcher.setHashAlgorithmName("MD5"); //配置加密的次數(shù) //retryLimitHashedCredentialsMatcher.setHashIterations(1024); //是否存儲(chǔ)為16進(jìn)制 //retryLimitHashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); return retryLimitHashedCredentialsMatcher; }
在shiroRealm中配置密碼比較器
/** * 身份認(rèn)證realm; (這個(gè)需要自己寫,賬號(hào)密碼校驗(yàn);權(quán)限等) * @return */ @Bean public ShiroRealm shiroRealm(){ ShiroRealm shiroRealm = new ShiroRealm(); ...... //配置自定義密碼比較器 shiroRealm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher()); return shiroRealm; }
在ehcache-shiro.xml添加緩存項(xiàng)
<!-- 登錄失敗次數(shù)緩存 注意 timeToLiveSeconds 設(shè)置為300秒 也就是5分鐘 可以根據(jù)自己的需求更改 --> <cache name="passwordRetryCache" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="0" timeToLiveSeconds="300" overflowToDisk="false" statistics="true"> </cache>
在LoginController中添加解除admin用戶限制方法
/** * 解除admin 用戶的限制登錄 * 寫死的 方便測(cè)試 * @return */ @RequestMapping("/unlockAccount") public String unlockAccount(Model model){ model.addAttribute("msg","用戶解鎖成功"); retryLimitHashedCredentialsMatcher.unlockAccount("admin"); return "login"; }
注意:為了方便測(cè)試,記得將 unlockAccount 權(quán)限改為 任何人可訪問。
在login.html頁面 添加 解鎖admin用戶的按鈕
<a href="/unlockAccount" rel="external nofollow" >解鎖admin用戶</a></button>
測(cè)試結(jié)果
總結(jié)
以上所述是小編給大家介紹的springboot整合shiro-登錄失敗次數(shù)限制,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Netty分布式Server啟動(dòng)流程服務(wù)端初始化源碼分析
本章主要講解server啟動(dòng)的關(guān)鍵步驟,?讀者只需要了解server啟動(dòng)的大概邏輯,?知道關(guān)鍵的步驟在哪個(gè)類執(zhí)行即可,?并不需要了解每一步的運(yùn)作機(jī)制,?之后會(huì)對(duì)每個(gè)模塊進(jìn)行深度分析2022-03-03SpringBoot中的FailureAnalyzer使用詳解
這篇文章主要介紹了SpringBoot中的FailureAnalyzer使用詳解,Spring Boot的FailureAnalyzer是一個(gè)接口,它用于在Spring Boot應(yīng)用啟動(dòng)失敗時(shí)提供有關(guān)錯(cuò)誤的詳細(xì)信息,這對(duì)于開發(fā)者來說非常有用,因?yàn)樗梢詭椭覀兛焖僮R(shí)別問題并找到解決方案,需要的朋友可以參考下2023-12-12Java實(shí)現(xiàn)字符數(shù)組全排列的方法
這篇文章主要介紹了Java實(shí)現(xiàn)字符數(shù)組全排列的方法,涉及Java針對(duì)字符數(shù)組的遍歷及排序算法的實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-12-12mybatis-plus數(shù)據(jù)權(quán)限實(shí)現(xiàn)代碼
這篇文章主要介紹了mybatis-plus數(shù)據(jù)權(quán)限實(shí)現(xiàn),結(jié)合了mybatis-plus的插件方式,做出了自己的注解方式的數(shù)據(jù)權(quán)限,雖然可能存在一部分的局限性,但很好的解決了我們自己去解析SQL的功能,需要的朋友可以參考下2023-06-06Spring @Value 設(shè)置默認(rèn)值的實(shí)現(xiàn)
這篇文章主要介紹了Spring @Value 設(shè)置默認(rèn)值的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Spring boot如何配置請(qǐng)求的入?yún)⒑统鰠son數(shù)據(jù)格式
這篇文章主要介紹了spring boot如何配置請(qǐng)求的入?yún)⒑统鰠son數(shù)據(jù)格式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11idea啟動(dòng)與jar包啟動(dòng)中使用resource資源文件路徑的問題
這篇文章主要介紹了idea啟動(dòng)與jar包啟動(dòng)中使用resource資源文件路徑的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07解決spring中redistemplate不能用通配符keys查出相應(yīng)Key的問題
這篇文章主要介紹了解決spring中redistemplate不能用通配符keys查出相應(yīng)Key的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11