Spring Security может многое сделать для вас.
Блокировка аккаунта, соль пароля. Но как насчет блокировщика грубой силы.
Это то, что вы должны сделать сами.
К счастью, Spring — достаточно гибкая структура, поэтому его не составляет особого труда.
Позвольте мне показать вам небольшое руководство, как это сделать для приложения Grails.
Прежде всего, вы должны включить springSecurityEventListener в вашем config.groovy
|
1
|
grails.plugins.springsecurity.useSecurityEventListener = true |
затем реализовать слушателей
в / src / bruteforce создавать классы
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
/**Registers all failed attempts to login. Main purpose to count attempts for particular account ant block user*/class AuthenticationFailureListener implements ApplicationListener { LoginAttemptCacheService loginAttemptCacheService @Override void onApplicationEvent(AuthenticationFailureBadCredentialsEvent e) { loginAttemptCacheService.failLogin(e.authentication.name) }} |
Далее мы должны создать слушатель для успешных входов
в той же упаковке
|
01
02
03
04
05
06
07
08
09
10
11
12
|
/** Listener for successfull logins. Used for reseting number on unsuccessfull logins for specific account*/class AuthenticationSuccessEventListener implements ApplicationListener{ LoginAttemptCacheService loginAttemptCacheService @Override void onApplicationEvent(AuthenticationSuccessEvent e) { loginAttemptCacheService.loginSuccess(e.authentication.name) }} |
Мы не помещали их в нашу папку grails-app, поэтому нам нужно преобразовать эти классы как весенние бобы.
Добавьте следующие строки в grails-app / conf / spring / resources.groovy
|
1
2
3
4
5
6
7
8
9
|
beans = { authenticationFailureListener(AuthenticationFailureListener) { loginAttemptCacheService = ref('loginAttemptCacheService') } authenticationSuccessEventListener(AuthenticationSuccessEventListener) { loginAttemptCacheService = ref('loginAttemptCacheService') }} |
Вы, вероятно, заметили использование LoginAttemptCacheService loginAttemptCacheService
Давайте реализуем это. Это был бы типичный сервис Grails
|
01
02
03
04
05
06
07
08
09
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
|
package com.picsel.officeanywhereimport com.google.common.cache.CacheBuilderimport com.google.common.cache.CacheLoaderimport com.google.common.cache.LoadingCacheimport java.util.concurrent.TimeUnitimport org.apache.commons.lang.math.NumberUtilsimport javax.annotation.PostConstructclass LoginAttemptCacheService { private LoadingCache attempts; private int allowedNumberOfAttempts def grailsApplication @PostConstruct void init() { allowedNumberOfAttempts = grailsApplication.config.brutforce.loginAttempts.allowedNumberOfAttempts int time = grailsApplication.config.brutforce.loginAttempts.time log.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) } }} |
Мы будем использовать CacheBuilder из библиотеки Google Guava. Так что добавьте следующую строку в BuildConfig.groovy
|
1
2
3
|
dependencies { runtime 'com.google.guava:guava:11.0.1' } |
И последний шаг — добавление конфигурации сервиса в cinfig.groovy.
|
1
2
3
4
5
|
brutforce { loginAttempts { time = 5 allowedNumberOfAttempts = 3 } |
Вот и все, вы готовы запустить ваше приложение.
Для типичного Java-проекта почти все будет одинаковым. Те же слушатели и те же службы.
Подробнее о весенних событиях безопасности
Подробнее о кэшировании с помощью Google Guava
Пользователь Grails может просто использовать этот плагин https://github.com/grygoriy/bruteforcedefender
Приятного кодирования и не забудьте поделиться!
Ссылка: Предотвратите атаку грубой силы с помощью Spring Security от нашего партнера по JCG Григория Михалюно в блоге Григория Михалюно .