Добавление пользователя в сеанс, логин Spring Security по умолчанию

#java #spring #spring-mvc #spring-security

#java #spring #spring-mvc #spring-безопасность

Вопрос:

Я настроил Spring Security для правильного перехвата и запроса пользователя на пользовательскую страницу входа, которая затем проходит правильную аутентификацию и добавляет пользовательские данные в SecurityContextHolder.

В дополнение к этому я теперь хочу добавить свой собственный пользовательский объект User, добавляемый в сеанс при каждом входе в систему; таким образом, код будет выглядеть следующим образом:

 public returnwhat? doMySupplementaryLogin() {

   UserDetails principal = (UserDetails) SecurityContextHolder.getContext()
                                .getAuthentication().getPrincipal();
   MyUser user = myUserService.getMyUser(principal.getUsername());

   add user to what ?
}
  

Куда пойдет этот код? Я хочу, чтобы была выполнена аутентификация nomral spring, а затем приведенный выше код поместит объект MyUser в сеанс, а затем отправит пользователя на исходный перехваченный URL / viewname. У меня сильное чувство, что я усложняю ситуацию больше, чем нужно…

Ответ №1:

Вы действительно усложняете … 🙂

Что вы хотите, так это добавить пользовательского поставщика аутентификации в обычный менеджер аутентификации Spring. Итак, вы бы настроили менеджер аутентификации следующим образом:

     <security:authentication-manager alias="authenticationManager">
      <security:authentication-provider user-service-ref="authServiceImpl">
        <security:password-encoder ref="passwordEncoder"/>
      </security:authentication-provider>
    </security:authentication-manager>
    <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>
  

Теперь вам нужно только определить компонент authServiceImpl внутри вашего контекста spring. Вы можете сделать это с помощью xml или аннотаций (мой предпочтительный способ).

 @Service
public class AuthServiceImpl implements AuthService {
  

Вам необходимо реализовать интерфейс AuthService. Просто реализуйте методы из интерфейса — должно быть довольно просто.
Вам не нужно помещать данные в SecurityContextHolder самостоятельно — spring сделает это.

Чего вы хотите, так это:

 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
     return MyUser user = myUserService.getMyUser(username);
}
  

Не стесняйтесь спрашивать, есть ли у вас какие-либо дополнительные вопросы.

РЕДАКТИРОВАТЬ: Или вы могли бы просто использовать свой класс UserService для реализации интерфейса — я просто сделал это так, потому что вы не предоставили свой класс UserService.

Комментарии:

1. спасибо, хорошо, как мне получить доступ к MyUser (который реализует UserDetails) в контроллере? А «Authservice» — это опечатка и должно быть «UserDetailsService»?

2. Извините, это не опечатка. На самом деле у меня есть другой интерфейс в моем authserviceimpl. AuthService действительно расширяет UserDetailsService.

3. Вы можете получить доступ к своему классу MyUser в своем контроллере, как и с любым другим компонентом Spring. автоматическое подключение или настройка в вашем applicationContext.xml

4. Как и любой другой компонент Spring? Но разве это не атрибут сеанса / в контексте безопасности? Я добиваюсь прогресса, как получить доступ к объекту MyUser из jsp (например, для отображения приветствуемого имени пользователя)?

5. Вам вообще не нужно обращаться к объекту User — вы можете получить доступ к UserPrincipal (объекту UserDetails, который вы вернули в методе loadUserByUsername), хотя: ${pageContext.request.userPrincipal.name} распечатает текущее имя пользователя, вошедшее в систему

Ответ №2:

или добавьте свой собственный AuthenticationSuccessHandler, например, этот класс, который я добавил, чтобы я мог хранить имя пользователя и пароль в сеансе, чтобы я мог входить в другие микросервисы, когда это необходимо:

 public class AuthenticationSuccessWithSessionHandler extends SavedRequestAwareAuthenticationSuccessHandler implements AuthenticationSuccessHandler, LogoutSuccessHandler {

    public static final String USERNAME = "username";
    public static final String PASSWORD = "password";

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        request.getSession().removeAttribute(USERNAME);
        request.getSession().removeAttribute(PASSWORD);
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        super.onAuthenticationSuccess(request, response, authentication);
        request.getSession().setAttribute(PASSWORD, request.getParameter(PASSWORD));
        request.getSession().setAttribute(USERNAME, request.getParameter(USERNAME));
    }
}
  

и зарегистрировал его

         AuthenticationSuccessWithSessionHandler successHandler = new AuthenticationSuccessWithSessionHandler();
        http.authorizeRequests().antMatchers("/login", "/logout", "/images", "/js").permitAll().antMatchers("/feeds/**")
                .authenticated().and().formLogin()
                .successHandler(successHandler)
                .and().logout().logoutUrl("/logout").logoutSuccessHandler(successHandler).logoutSuccessUrl("/login");
  

обратите внимание, что extends SavedRequestAwareAuthenticationSuccessHandler сохраняет исходный URL-адрес и восстанавливает его после успешного входа в систему.