Before the Shiro security how to combine the verification code, this time talk about how to limit the number of user login attempts to prevent multiple attempts, brute force password situation appears. To limit the number of user login attempts, it is necessary to record the user name password verification failure, Shiro user name password Authentication to the Credentialsmatcher
So check in Credentialsmatcher, log the number of logins is the simplest way. Shiro Natural and Ehcache is a good pair of partners, whether it is a single machine or a cluster, you can store the number of login attempts in Ehcache information.
Now introduce a simple login verification practice, implement a retrylimitcredentialsmatchers inheritance to Hashedcredentialsmatcher, join the cache, and verify the number of user name attempts before each authentication of the user name password. If more than 5 times throw an attempt too many exceptions, or verify the user name password, verify the success of the number of attempts to clear zero, unsuccessful, and then exit directly. This relies on Ehcache's own timetoidleseconds to ensure lock -in time (the last attempt interval after the account lockout timetoidleseconds seconds after the automatic purge).
Public class retrylimitcredentialsmatcher extends hashedcredentialsmatcher {//cluster may cause more than 5 validations to occur because Atomicinteger can only guarantee a single node concurrencyPrivateCache<string, atomicinteger> Passwordretrycache; Public Retrylimithashedcredentialsmatcher(CacheManager CacheManager) {Passwordretrycache = Cachemanager.getcache ("Passwordretrycache"); }@Override Public Boolean Docredentialsmatch(Authenticationtoken token, authenticationinfo info) {String username = (string) token.getprincipal ();//retry count + 1Atomicinteger RetryCount = passwordretrycache.get (username);if(NULL= = RetryCount) {RetryCount =NewAtomicinteger (0); Passwordretrycache.put (username, retrycount); }if(Retrycount.incrementandget () >5) {Logger.warn ("Username:"+ Username +"tried to login + than 5 times in period");Throw NewExcessiveattemptsexception ("Username:"+ Username +"tried to login + than 5 times in period"); }BooleanMatches =Super. Docredentialsmatch (token, info);if(matches) {//clear Retry DataPasswordretrycache.remove (username); }returnMatches }}
- Spring Configuration CacheManager
<bean id= "Springcachemanager" class=" Org.springframework.cache.ehcache.EhCacheCacheManager "> < property name="CacheManager" ref="Ehcachemanager"/> </Bean> <!--ehcache--> <bean id= "Ehcachemanager" class=" Org.springframework.cache.ehcache.EhCacheManagerFactoryBean "> < property name="Configlocation" value="classpath:ehcache/ Ehcache.xml "/> </Bean>
- Ehcache Configuration
<ehcache name="es"> <diskstore path="Java.io.tmpdir"/> <!--login Record cache lock 100 min -- <cache Name="Passwordretrycache"maxentrieslocalheap="20000" Eternal="false"timetoidleseconds="36000"timetoliveseconds= "0"overflowtodisk="false"statistics="false"> </Cache></ehcache>
- Spring Shiro Configuration
Userrealm inherits Authorizingrealm, and in the Getauthenticationinfo method of its parent class Authenticatingrealm calls Credentialsmatcher's
Docredentialsmatch
To verify that the user entered the user name password to match.
<bean id= "credentialsmatcher" class=" Com.cloud.service.security.credentials.RetryLimitCredentialsMatcher "> <constructor-arg ref="Springcachemanager"/> < property name= "storedcredentialshexencoded" value=" True "/> </Bean> <bean id="Myrealm" class="Com.cloud.service.security.UserRealm" > < property name= "credentialsmatcher" ref=" Credentialsmatcher "/> < property name="cachingenabled" value="false"/ > <!--<property name= "authenticationcachingenabled" value= "true"/>--> <!--<property name= "Authenticationcachename" value= "Authenticationcache"/>--> <!--<property name= "authorizationcachingenabled" value= "true"/>--> <!--<property name= "Authorizationcachename" value= "Authorizationcache"/>--> </Bean>
Shiro Security Limit number of login attempts