/**
Registers all failed attempts to login. Main purpose to count attempts for particular account ant block user*/
class AuthenticationFailureListener implements ApplicationListener {LoginAttemptCacheService loginAttemptCacheService@Overridevoid onApplicationEvent(AuthenticationFailureBadCredentialsEvent e) {loginAttemptCacheService.failLogin(e.authentication.name)}
}
接下來,我們必須創建用于成功登錄的偵聽器 在同一包裝中
/**Listener for successfull logins. Used for reseting number on unsuccessfull logins for specific account
*/
class AuthenticationSuccessEventListener implements ApplicationListener{LoginAttemptCacheService loginAttemptCacheService@Overridevoid onApplicationEvent(AuthenticationSuccessEvent e) {loginAttemptCacheService.loginSuccess(e.authentication.name)}
}
我們沒有將它們放在grails-app文件夾中,因此我們需要將這些類作為spring bean重新命名。 在grails-app / conf / spring / resources.groovy中添加下一行
package com.picsel.officeanywhereimport com.google.common.cache.CacheBuilder
import com.google.common.cache.CacheLoader
import com.google.common.cache.LoadingCacheimport java.util.concurrent.TimeUnit
import org.apache.commons.lang.math.NumberUtils
import javax.annotation.PostConstructclass LoginAttemptCacheService {private LoadingCacheattempts;private int allowedNumberOfAttemptsdef grailsApplication@PostConstructvoid init() {allowedNumberOfAttempts = grailsApplication.config.brutforce.loginAttempts.allowedNumberOfAttemptsint time = grailsApplication.config.brutforce.loginAttempts.timelog.info 'account block configured for $time minutes'attempts = CacheBuilder.newBuilder().expireAfterWrite(time, TimeUnit.MINUTES).build({0} as CacheLoader);}/*** Triggers on each unsuccessful login attempt and increases number of attempts in local accumulator* @param login - username which is trying to login* @return*/def failLogin(String login) {def numberOfAttempts = attempts.get(login)log.debug 'fail login $login previous number for attempts $numberOfAttempts'numberOfAttempts++if (numberOfAttempts > allowedNumberOfAttempts) {blockUser(login)attempts.invalidate(login)} else {attempts.put(login, numberOfAttempts)}}/*** Triggers on each successful login attempt and resets number of attempts in local accumulator* @param login - username which is login*/def loginSuccess(String login) {log.debug 'successfull login for $login'attempts.invalidate(login)}/*** Disable user account so it would not able to login* @param login - username that has to be disabled*/private void blockUser(String login) {log.debug 'blocking user: $login'def user = User.findByUsername(login)if (user) {user.accountLocked = true;user.save(flush: true)}}
}