Shiro security limits login attempts

http://blog.csdn.net/cloud_ll/article/details/44124189
I talked about how Shiro Security combines verification codes. This time I talk about how to limit the number of user login attempts to prevent multiple attempts and brute force password cracking. To limit the number of user login attempts, it is necessary to record the failure of username and password verification. The verification of username and password in Shiro is handed over to CredentialsMatcher
, so it is the easiest way to check in CredentialsMatcher and record the number of logins. Shiro and Ehcache are a good partner by nature. Whether it is a single machine or a cluster, the number of login attempts can be stored in Ehcache.
Now introduce a simple method of login times verification, implement a RetryLimitCredentialsMatchers inherited from HashedCredentialsMatcher, add the cache, verify the number of user name attempts before verifying the user name and password each time, if it exceeds 5 times, throw too many attempts exception, otherwise verify the user Name and password, if the verification succeeds, the number of attempts will be cleared, and if it is unsuccessful, it will exit directly. Here, the timeToIdleSeconds that comes with Ehcache is used to ensure the locking time (the last attempt after the account is locked is automatically cleared after the interval of timeToIdleSeconds seconds).

public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher {

//In the cluster, there may be more than 5 verifications, because AtomicInteger can only guarantee single-node concurrency    
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();
        //retry count + 1
        AtomicInteger retryCount = passwordRetryCache.get(username);
        if(null == retryCount) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if(retryCount.incrementAndGet() > 5) {
            logger.warn("username: " + username + " tried to login more than 5 times in period");
            throw new ExcessiveAttemptsException("username: " + username + " tried to login more than 5 times in period"
); }
         boolean matches = super.doCredentialsMatch(token, info);
         if(matches) {
              //clear retry data
              passwordRetryCache.remove(username);
         }
         return matches;
    }
}

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"/>

    <!-- The login record cache is locked for 100 minutes-->
    <cache name="passwordRetryCache"
           maxEntriesLocalHeap="20000"
           eternal="false"
           timeToIdleSeconds="36000"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="false">
    </cache>

</ehcache>

Spring Shiro configures
UserRealm to inherit AuthorizingRealm, and calls
doCredentialsMatch of credentialsMatcher in the getAuthenticationInfo method of its parent class AuthenticatingRealm
to verify whether the user input username and password 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>

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326992436&siteId=291194637