Я упоминал в своем посте « Добавление входа в социальную сеть в блог 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
|
@Configurationpublic 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 .