Аутентификация / авторизация Spring Security через конечную точку REST
В моем приложении Spring Boot с веб-сервисами RESTful я настроил Spring Security вместе с Spring Social и SpringSocialConfigurer
,
Прямо сейчас у меня есть два способа аутентификации / авторизации - через имя пользователя / пароль и через социальные сети, например, как Twitter.
Чтобы реализовать аутентификацию / авторизацию через мою собственную конечную точку RESTful в контроллере Spring MVC REST, я добавил следующий метод:
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Authentication login(@RequestBody LoginUserRequest userRequest) {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userRequest.getUsername(), userRequest.getPassword()));
boolean isAuthenticated = isAuthenticated(authentication);
if (isAuthenticated) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
return authentication;
}
private boolean isAuthenticated(Authentication authentication) {
return authentication != null && !(authentication instanceof AnonymousAuthenticationToken) && authentication.isAuthenticated();
}
но я не уверен, что именно должно быть возвращено клиенту после успешного завершения /login
вызов конечной точки. Я думаю, что возвращение объекта полной аутентификации является излишним.
Что следует вернуть клиенту в случае успешной аутентификации?
Не могли бы вы сказать мне, как правильно реализовать этот метод входа?
Кроме того, в случае входа в RESTfull у меня будет UsernamePasswordAuthenticationToken
а в случае входа через твиттер у меня будет SocialAuthenticationToken
Можно ли использовать разные токены в одном приложении?
2 ответа
Вы можете настроить, что возвращать при успешной аутентификации, переопределив методы в SimpleUrlAuthenticationSuccessHandler
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public CustomAuthenticationSuccessHandler() {
super();
setRedirectStrategy(new NoRedirectStrategy());
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
super.onAuthenticationSuccess(request, response, authentication);
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=UTF-8");
response.getWriter().print(mapper.writeValueAsString(objectToBereturned);
response.getWriter().flush();
}
protected class NoRedirectStrategy implements RedirectStrategy {
@Override
public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
throws IOException {
// any redirect if required. leave the implementation black if not needed
}
}
}
Кроме того, вы также можете обработать реакцию на ошибку:
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
Успешные звонки всегда должны возвращать код ответа. В вашем случае это должно быть просто 200 ОК. При сбое 401 Несанкционированный. Наличие разных токенов абсолютно нормально, вы не можете использовать их в любом случае.
Лично я предпочел бы обрабатывать конечные точки входа в систему через фильтры Spring Security, а не контроллеры, поскольку вы можете лучше контролировать поток.