Войдите в систему с функцией mem-me в Spring 3.1

17

В настоящее время я регистрирую пользователей программно (например, когда они подключаются к Facebook или другим способом, кроме использования моей формы входа):

SecurityContextHolder.getContext().setAuthentication(
  new UsernamePasswordAuthenticationToken(user, "", authorities)
);

Вместо этого я хочу войти в систему, как если бы они установили параметр «Запомнить меня» в форме входа. Поэтому я предполагаю, что мне нужно использовать RememberMeAuthenticationToken вместо UsernamePasswordAuthenticationToken ? Но что я ставлю для аргумента key конструктора?

RememberMeAuthenticationToken(String key, Object principal, Collection<? extends GrantedAuthority> authorities) 

ОБНОВЛЕНИЕ . Я использую Поддержанный подход к токенам, описанный здесь . Таким образом, нет никакого ключа, как в методе Token Approach на основе простого хаша.

    
задан at. 18.10.2011 в 14:05
источник
  • Вы хотите сказать, что просто хотите установить аутентификацию в SecurityContextHolder? Или вам нужно также установить cookie «помнить-я»? –  sourcedelica 18.10.2011 в 17:15
  • Я хочу зарегистрировать человека, и мое приложение запоминает их, поэтому им не нужно снова входить в систему. –  at. 18.10.2011 в 18:52

2 ответа

13

Я предполагаю, что у вас уже есть <remember-me> , установленное в вашей конфигурации.

Как помню, как работает, он устанавливает cookie, который распознается, когда пользователь возвращается на сайт после истечения срока их сеанса.

Вам нужно подклассифицировать RememberMeServices ( TokenBased или PersistentTokenBased ), которое вы используете, и сделать onLoginSuccess () общедоступным. Например:

public class MyTokenBasedRememberMeServices extends PersistentTokenBasedRememberMeServices {
    @Override
    public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {
        super.onLoginSuccess(request, response, successfulAuthentication);
    }   
} 

<remember-me services-ref="rememberMeServices"/>

<bean id="rememberMeServices" class="foo.MyTokenBasedRememberMeServices">
    <property name="userDetailsService" ref="myUserDetailsService"/>
    <!-- etc -->
</bean>

Внесите свои RememberMeServices в bean-компонент, где вы выполняете вход в систему. Затем наберите onLoginSuccess() , используя созданный вами UsernamePasswordAuthenticationToken. Это установит файл cookie.

UsernamePasswordAuthenticationToken auth = 
    new UsernamePasswordAuthenticationToken(user, "", authorities);
SecurityContextHolder.getContext().setAuthentication(auth);
getRememberMeServices().onLoginSuccess(request, response, auth);  

UPDATE

@at улучшилось, без подкласса RememberMeServices:

UsernamePasswordAuthenticationToken auth = 
    new UsernamePasswordAuthenticationToken(user, "", authorities);
SecurityContextHolder.getContext().setAuthentication(auth);

// This wrapper is important, it causes the RememberMeService to see
// "true" for the "_spring_security_remember_me" parameter.
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
    @Override public String getParameter(String name) { return "true"; }            
};

getRememberMeServices().loginSuccess(wrapper, response, auth);  
    
ответ дан sourcedelica 18.10.2011 в 19:32
  • В моей конфигурации XML безопасности я просто использую <mem-me token-validity-seconds="31536000" data-source-ref="dataSource" /> в элементе <http>. Где определяется компонент TokenBasedRememberMeServices? Используя этот механизм, мне больше не нужно связываться с SecurityContextHolder? Похоже, это гораздо лучшее решение для программного входа в систему. –  at. 18.10.2011 в 23:05
  • Я предполагаю, что мне нужны PersistentTokenBasedRememberMeServices вместо TokenBasedRememberMeServices. Но в любом случае, и если я могу ввести его в контроллер, где я пытаюсь войти в систему с функцией mem-me, loginSuccess () не выглядит так, как я хочу. Javadocs говорит: «Изучает входящий запрос и проверяет наличие настроенного параметра« запомнить меня ». Если он присутствует или если alwaysRemember установлен в true, вызывает onLoginSucces». –  at. 19.10.2011 в 00:52
  • Вы можете сделать это как для постоянных, так и для обычных версий TokenBasedRememberMeServices. Я просто проверил источник 3.1 (извините, я пропустил это), и это то же самое. –  sourcedelica 19.10.2011 в 05:01
  • Добавлены некоторые примеры кода –  sourcedelica 23.10.2011 в 06:13
  • Нет необходимости расширять класс или использовать оболочку. Просто установите alwaysRemember = true на PersistentTokenBasedRememberMeServices. К сожалению, кажется, что это невозможно сделать с помощью XML-элемента <remember-me>, поэтому вам нужно будет определить bean PersistentTokenBasedRememberMeServices и установить для этого свойства значение true. После этого normal rememberMeServices.loginSuccess (req, res, auth) создает cookie и постоянную запись –  maximdim 13.08.2015 в 05:43
Показать остальные комментарии
2

Это источник для конструктора.

public RememberMeAuthenticationToken(String key, Object principal, Collection<? extends GrantedAuthority> authorities) {
    super(authorities);

    if ((key == null) || ("".equals(key)) || (principal == null) || "".equals(principal)) {
        throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
    }

    this.keyHash = key.hashCode();
    this.principal = principal;
    setAuthenticated(true);
}

Ключ hashed и используется для определения того, является ли аутентификация, используемая для этого пользователя в контексте безопасности, не «поддельной».

Посмотрите источник RememberMeAuthenicationProvider .

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (!supports(authentication.getClass())) {
        return null;
    }

    if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) {
        throw new BadCredentialsException(messages.getMessage("RememberMeAuthenticationProvider.incorrectKey",
                "The presented RememberMeAuthenticationToken does not contain the expected key"));
    }

    return authentication;
}

Чтобы ответить на ваш вопрос, вам нужно передать хэш-код поля key Authentication , представляющего пользователя .

    
ответ дан Simeon 18.10.2011 в 15:38
  • Я до сих пор не знаю, что делать. Как получить аутентификацию, представляющую пользователя. И что именно я передаю в качестве ключевого аргумента? –  at. 18.10.2011 в 18:52