2016-02-06 2 views
5

У меня есть приложение весной загрузки с WebSecurityConfigurerAdapter сконфигурированной как это -Spring загрузки - объект возвращения пользователя после входа в систему

http.csrf().disable() 
        .exceptionHandling() 
        .authenticationEntryPoint(restAuthenticationEntryPoint) 
        .and() 
       .authorizeRequests() 
        .antMatchers("/user/*", "/habbit/*").authenticated() 
        .and() 
       .formLogin() 
        .loginProcessingUrl("/login") 
        .permitAll() 
        .usernameParameter("email") 
        .passwordParameter("pass") 
        .successHandler(authenticationSuccessHandler) 
        .failureHandler(new SimpleUrlAuthenticationFailureHandler()) 
        .and() 
       .logout() 
        .logoutUrl("/logout") 
        .invalidateHttpSession(true); 

Могу ли я добавить что-то вроде собственного контроллера, который, после успешной аутентификации, вернуться назад обычай объект с некоторыми сведениями об аутентифицированном пользователе?

Обновление: Для ясности я использую угловое приложение в качестве клиента. В настоящее время мне нужно сделать 2 запроса от моего клиента к серверу: 1. POST-запрос на URL-адрес для аутентификации. 2. Запрос GET для получения аутентифицированных пользовательских данных.

Моя цель - получить 1-й запрос, чтобы вернуть мне информацию пользователя, поэтому мне не нужно делать запрос 2dn. В настоящее время 1-й запрос только аутентифицирует пользователя, создает сеанс на сервере и отправляет ответ «200 OK» с данных. Я хочу, чтобы он возвращал ответ успеха с данными о пользователе.

Ответил:

Правильный ответ в комментариях, так что я буду писать здесь: мне нужно перенаправить с моей successHandler на мой контроллер, который в свою очередь, возвращает вошедшего в информации о пользователе (в моем случае контроллер находится в URL «/ пользователь/я»:

@Override 
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, 
             Authentication authentication) throws ServletException, IOException { 
     clearAuthenticationAttributes(request); 
     getRedirectStrategy().sendRedirect(request, response, "/user/me"); 
    } 
+0

Вам необходим пользователь при работе с каким-то будущим запросом, или же вам нужно «событие» прямо на входе в системе? (обе поддерживаются весной (безопасность), но она работает совершенно по-разному) - для первого взгляните на этот вопрос: http://stackoverflow.com/q/8764545/280244, для второго взгляните на этот вопрос http://stackoverflow.com/questions/15493237/how-to-correctly-update-the-login-date-time-after-successful-login-with-spring-s – Ralph

+1

У меня есть угловой интерфейс и после успешного запроса POST аутентификации я хотел бы иметь некоторые данные пользователя в ответе, чтобы показать их на моей веб-странице. – Tomas

+0

Скажите, пожалуйста, как вы управляли логином по запросу POST? –

ответ

7

Если я правильно понимаю вашу проблему правильно, я могу предложить следующий способ

Прежде всего, вы должны реализовать класс. , который будет содержать информацию о пользователе. Этот класс должен быть унаследован от org.springframework.security.core.userdetails.User:

public class CustomUserDetails extends User { 

    public CustomUserDetails(String username, String password, 
     Collection<? extends GrantedAuthority> authorities) {    
     super(username, password, authorities); 
    } 

    //for example lets add some person data   
    private String firstName; 
    private String lastName; 

    //getters and setters 
} 

Следующий шаг, вы должны создать вам собственную реализацию интерфейса org.springframework.security.core.userdetails.UserDetailsService:

@Service 
public class CustomUserDetailService implements UserDetailsService{ 

    @Override 
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException{   

     if(StringUtils.isEmpty(userName)) 
      throw new UsernameNotFoundException("User name is empty"); 

     //if you don't use authority based security, just add empty set 
     Set<GrantedAuthority> authorities = new HashSet<>(); 
     CustomUserDetails userDetails = new CustomUserDetails(userName, "", authorities);    

     //here you can load user's data from DB or from 
     //any other source and do: 
     //userDetails.setFirstName(firstName); 
     //userDetails.setLastName(lastName); 

     return userDetails; 
    } 

} 

Как вы видите, этот класс имеет только один метод, где вы можете загрузить и установить пользовательские данные пользователя. Обратите внимание, что я отметил этот класс аннотацией @Service. Но вы можете зарегистрировать его в своем Java-config или XML-контексте.

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

@Controller 
public class MyController{ 

    @RequestMapping("/mapping") 
    public String myMethod(Principal principal, ModelMap model){ 
     CustomUserDetails userDetails = (CustomUserDetails)principal; 
     model.addAttribute("firstName", userDetails.getFirstName()); 
     model.addAttribute("lastName", userDetails.getLastName()); 
    } 
} 

Или еще один способ:

@Controller 
public class MyController{ 

    @RequestMapping("/mapping") 
    public String myMethod(ModelMap model){ 
     Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
     CustomUserDetails userDetails = (CustomUserDetails)auth.getPrincipal(); 
     model.addAttribute("firstName", userDetails.getFirstName()); 
     model.addAttribute("lastName", userDetails.getLastName()); 
    } 
} 

Этот метод можно использовать в других местах, где Spring не передает основную информацию автоматически.

Чтобы перейти к определенному адресу после успешной аутентификации, вы можете использовать SimpleUrlAuthenticationSuccessHandler.Просто создайте его в конфигурации:

@Bean 
public SavedRequestAwareAuthenticationSuccessHandler successHandler() { 
    SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); 
    successHandler.setTargetUrlParameter("/succeslogin"); 
    return successHandler; 
} 

и использовать его в конфигурации:

http.formLogin() 
    .loginProcessingUrl("/login") 
    .permitAll() 
    .usernameParameter("email") 
    .passwordParameter("pass") 
    .successHandler(successHandler()) 

после этого вы можете создать контроллер, который будет отправлять ответ от speciafied URL:

@Controller 
@RequestMapping("/sucesslogin") 
public class SuccessLoginController{ 

    @RequestMapping(method = RequestMethod.POST) 
    public String index(ModelMap model, Principal principal){ 
     //here you can return view with response 
    } 

} 

Из-за чего вы можете вернуть не только просмотр, но и ответ JSON (используя аннотацию @ResponseBody), или что-то еще, зависит от вас от интерфейса. Надеюсь, это будет полезно.

+0

было бы решить мою проблему если CustomUserDetails будет возвращен с успешным ответом на аутентификацию. Например. Я отправляю запрос POST, весна аутентифицировала меня и возвращает мне ответ успеха вместе с этим объектом CustomUserDetails. Возможно ли это? – Tomas

+0

Несомненно, вы можете перенаправить из 'authenticationSuccessHandler' в методу контроллера, и этот метод контроллера может вернуть все, что вы хотели бы вернуть. –

+0

Можете ли вы написать это в ответ? Может быть, с примером? Я буду отмечать это как принято. – Tomas

1

В принятом ответе вам нужны два вызова, чтобы получить нужные данные. Просто верните данные после входа в пользовательский AjaxAuthenticationSuccessHandler вот так.

@Bean 
public AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() { 
    return new AjaxAuthenticationSuccessHandler() { 

     @Override 
     public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
      response.getWriter().write(new ObjectMapper().writeValueAsString(new UserAuthenticationResponse(authentication.getName(), 123l))); 
      response.setStatus(200); 
     } 

    }; 
} 

и зарегистрировать successhandler:

http.successHandler(ajaxAuthenticationSuccessHandler())