Я упоминал в своем посте « Добавление входа в социальную сеть в блог Jiwhiz», что функция RememberMe не работает с Spring Social Security. Ну, это потому, что приложение не аутентифицирует пользователя по имени пользователя и паролю, и полностью зависит от социальных сайтов (таких как Google, Facebook и Twitter), чтобы сделать работу. Конфигурация Spring Security по умолчанию не может справиться с этой ситуацией. Spring Security может быть самым сложным программным обеспечением среди всех проектов Spring Portfolio . Для корректной работы очень простого веб-приложения с безопасностью требуется около 10 фильтров. Чтобы упростить разработку приложений, Spring Security предоставляет конфигурацию пространства имен, начиная с версии 2.0, для автоматической настройки всех необходимых компонентов вместе, поэтому разработчикам не нужно разбираться в деталях. Он работает очень хорошо для большинства веб-приложений, если только ваше приложение не отличается от традиционного.
После того, как я изменил процесс входа в систему с аутентификации по имени пользователя на Spring Social Security без пароля, старая конфигурация для запомнить меня больше не работала. В справочном документе Spring Security имеется очень мало объяснений об аутентификации «Помни меня» , поэтому я купил книгу Spring Security 3.1, написанную Робом Уинчем, руководителем проекта Spring Security. В книге есть целая глава, рассказывающая об услугах Remember-Me, и она очень помогла мне понять, как работает функция Remember-Me в Spring Security. После прочтения книги я чувствую, что намного легче читать исходный код Spring Security, а чтение исходного кода всегда доставляет удовольствие.
Поскольку я не храню пароли для учетных записей пользователей, TokenBasedRememberMeServices по умолчанию не может работать с моим приложением, и я не хочу создавать свои собственные RememberMeServices — слишком много работы. К счастью, существует еще один подход к постоянным токенам, который заключается в хранении токенов в базе данных и сравнении токенов в файлах cookie. Все, что мне нужно, это настроить PersistentTokenBasedRememberMeServices в моем приложении с PersistentTokenRepository для хранения токенов. Spring Security предоставляет реализацию PersistentTokenRepository в JDBC, и я обнаружил, что написать собственную реализацию MongoDB после прочтения исходного кода тривиально.
Первым шагом является сохранение данных PersistentRememberMeToken в MongoDB. Мне нужно добавить класс сущности домена для него:
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
|
@Document (collection = 'RememberMeToken' ) public class RememberMeToken extends BaseEntity{ private String username; @Indexed private String series; private String tokenValue; private Date date; ... // getter/setter omitted public RememberMeToken(){ } public RememberMeToken(PersistentRememberMeToken token){ this .series = token.getSeries(); this .username = token.getUsername(); this .tokenValue = token.getTokenValue(); this .date = token.getDate(); } } |
Далее, используйте Spring Data, чтобы добавить хранилище для сущности:
1
2
3
4
|
public interface RememberMeTokenRepository extends MongoRepository<RememberMeToken, String>{ RememberMeToken findBySeries(String series); List<RememberMeToken> findByUsername(String username); } |
Тогда единственное относительно тяжелое кодирование — это реализовать PersistentTokenRepository для MongoDB:
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
|
public class MongoPersistentTokenRepositoryImpl implements PersistentTokenRepository { private final RememberMeTokenRepository rememberMeTokenRepository; public MongoPersistentTokenRepositoryImpl(RememberMeTokenRepository rememberMeTokenRepository){ this .rememberMeTokenRepository = rememberMeTokenRepository; } @Override public void createNewToken(PersistentRememberMeToken token) { RememberMeToken newToken = new RememberMeToken(token); this .rememberMeTokenRepository.save(newToken); } @Override public void updateToken(String series, String tokenValue, Date lastUsed) { RememberMeToken token = this .rememberMeTokenRepository.findBySeries(series); if (token != null ){ token.setTokenValue(tokenValue); token.setDate(lastUsed); this .rememberMeTokenRepository.save(token); } } @Override public PersistentRememberMeToken getTokenForSeries(String seriesId) { RememberMeToken token = this .rememberMeTokenRepository.findBySeries(seriesId); return new PersistentRememberMeToken(token.getUsername(), token.getSeries(), token.getTokenValue(), token.getDate()); } @Override public void removeUserTokens(String username) { List<RememberMeToken> tokens = this .rememberMeTokenRepository.findByUsername(username); this .rememberMeTokenRepository.delete(tokens); } } |
Остальная часть работы — вся конфигурация. Мне нужно связать их вместе в классе конфигурации Java:
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
|
@Configuration public class SocialAndSecurityConfig { @Inject private Environment environment; @Inject private AccountService accountService; @Inject private AuthenticationManager authenticationManager; @Inject private RememberMeTokenRepository rememberMeTokenRepository; ... @Bean public RememberMeServices rememberMeServices(){ PersistentTokenBasedRememberMeServices rememberMeServices = new PersistentTokenBasedRememberMeServices( environment.getProperty( 'application.key' ), accountService, persistentTokenRepository()); rememberMeServices.setAlwaysRemember( true ); return rememberMeServices; } @Bean public RememberMeAuthenticationProvider rememberMeAuthenticationProvider(){ RememberMeAuthenticationProvider rememberMeAuthenticationProvider = new RememberMeAuthenticationProvider(environment.getProperty( 'application.key' )); return rememberMeAuthenticationProvider; } @Bean public PersistentTokenRepository persistentTokenRepository() { return new MongoPersistentTokenRepositoryImpl(rememberMeTokenRepository); } } |
Последний шаг заключается в добавлении службы запомнить меня в конфигурационный файл безопасности xml, который является последним фрагментом конфигурации XML, и мы не можем сейчас его устранить. (Обновление: новый проект Spring Security Java Config заменит конфигурацию xml на конфигурацию Java в Spring Security.)
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
|
<? xml version = '1.0' encoding = 'UTF-8' ?> xsi:schemaLocation=' http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd'> < http use-expressions = 'true' entry-point-ref = 'socialAuthenticationEntryPoint' > < custom-filter position = 'PRE_AUTH_FILTER' ref = 'socialAuthenticationFilter' /> < logout logout-url = '/signout' delete-cookies = 'JSESSIONID' /> < remember-me services-ref = 'rememberMeServices' /> <!-- Configure these elements to secure URIs in your application --> < intercept-url pattern = '/favicon.ico' access = 'permitAll' /> < intercept-url pattern = '/robots.txt' access = 'permitAll' /> < intercept-url pattern = '/resources/**' access = 'permitAll' /> < intercept-url pattern = '/signin' access = 'permitAll' requires-channel = '#{environment[' application.secureChannel']}' /> < intercept-url pattern = '/signin/*' access = 'permitAll' requires-channel = '#{environment[' application.secureChannel']}' /> < intercept-url pattern = '/presentation/**' access = 'hasRole(' ROLE_USER')' requires-channel = '#{environment[' application.secureChannel']}' /> < intercept-url pattern = '/myAccount/**' access = 'hasRole(' ROLE_USER')' requires-channel = '#{environment[' application.secureChannel']}' /> < intercept-url pattern = '/myPost/**' access = 'hasRole(' ROLE_AUTHOR')' requires-channel = '#{environment[' application.secureChannel']}' /> < intercept-url pattern = '/admin/**' access = 'hasRole(' ROLE_ADMIN')' requires-channel = '#{environment[' application.secureChannel']}' /> < intercept-url pattern = '/**' access = 'permitAll' /> </ http > < authentication-manager alias = 'authenticationManager' > < authentication-provider ref = 'socialAuthenticationProvider' /> < authentication-provider ref = 'rememberMeAuthenticationProvider' /> </ authentication-manager > </ beans:beans > |
Это все, что нужно для добавления аутентификации Remember-Me в мое приложение для блога. Теперь вы можете войти через Google / Facebook / Twitter на мой сайт, и сайт будет постоянно помнить вас в течение следующих двух недель.
Ссылка: добавьте аутентификацию RememberMe с помощью Spring Security от нашего партнера по JCG Юаня Цзи в блоге Jiwhiz .