Вернуть ответ RESTful/json вместо формы входа в Spring boot OAUTH2

Я изо всех сил пытаюсь вернуть ответ json, когда пользователь не вошел в систему, вместо того, чтобы возвращать форму входа в html.

Приложение использует только @RestController, и мне не нужна веб-поддержка.

    http
        .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .httpBasic().disable();

Когда я делаю запрос на получение с помощью браузера или почтальона, я получаю форму входа в Spring HTML по умолчанию.

security.basic.enabled=true

Я использую OATH2, и когда я запрашиваю токен, он отлично работает, и я получаю такой ответ:

{
  "access_token": "227803d1-fe94-4e31-b496-3a03bafb9479",
  "token_type": "bearer",
  "refresh_token": "322f4ee9-4c48-4e06-a129-f4b6af93d664",
  "expires_in": 43199,
  "scope": "read write"
}

Почему-то это работает правильно в этом примере:

https://github.com/royclarkson/spring-rest-service-oauth

И когда я не авторизован, я хочу вернуть что-то вроде этого:

{
  "error": "unauthorized",
  "error_description": "An Authentication object was not found in the SecurityContext"
}

Но я получаю форму входа, и мне нужен ответ выше. Что я делаю не так? Я буквально не понимаю, почему это работает в примере с GitHub, а не в моем случае. Есть ли способ полностью отключить форму входа и заставить ответ json?


person Kramer    schedule 29.03.2017    source источник
comment
так почему вы добавляете .formLogin() в свой конфиг?   -  person chaoluo    schedule 29.03.2017
comment
даже без это делает   -  person Kramer    schedule 30.03.2017


Ответы (2)


AuthenticationEntryPoint используется для обработки исключений в Spring Security.

Если вы добавили oauth2 в свой pom, вы можете использовать OAuth2AuthenticationEntryPoint для своей точки входа, точка входа предназначена для обработки исключений безопасности spring, если вы используете базовую для своей аутентификации, вы можете настроить следующим образом

http
  .httpBasic().authenticationEntryPoint(getCustomerEntryPoint());

@Bean
protected AuthenticationEntryPoint getCustomerEntryPoint() {
    return new OAuth2AuthenticationEntryPoint();
}

как вы можете видеть обработку исключений в OAuth2AuthenticationEntryPoint

// Try to extract a SpringSecurityException from the stacktrace
    Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e);
    Exception ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType(
            OAuth2Exception.class, causeChain);

    if (ase != null) {
        return handleOAuth2Exception((OAuth2Exception) ase);
    }

    ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class,
            causeChain);
    if (ase != null) {
        return handleOAuth2Exception(new UnauthorizedException(e.getMessage(), e));
    }

    ase = (AccessDeniedException) throwableAnalyzer
            .getFirstThrowableOfType(AccessDeniedException.class, causeChain);
    if (ase instanceof AccessDeniedException) {
        return handleOAuth2Exception(new ForbiddenException(ase.getMessage(), ase));
    }

    ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer
            .getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain);
    if (ase instanceof HttpRequestMethodNotSupportedException) {
        return handleOAuth2Exception(new MethodNotAllowed(ase.getMessage(), ase));
    }

    return handleOAuth2Exception(new ServerErrorException(e.getMessage(), e));

он попытается получить OAuth2Exception, AuthenticationException, AccessDeniedException по порядку, я думаю, вы можете использовать это.

И вы также можете настроить ExceptionTranslationFilter, этот фильтр находится в цепочке безопасности spring, и он будет перехватывать и обрабатывать исключения после него, например AuthenticationException, AccessDeniedException, и это основная точка входа, которая будет полезна для большинства методов аутентификации, таких как FormLogin .

http
  .exceptionHandling().authenticationEntryPoint(getCustomerEntryPoint());

Если вы не используете spring oauth2, теперь вы понимаете AuthenticationEntryPoint, поэтому вы также можете реализовать свой собственный AuthenticationEntryPoint и настроить свой ответ на исключение, просто переопределив метод commence, например

BasicAuthenticationEntryPoint: он вернет заголовок «WWW-Authenticate» LoginUrlAuthenticationEntryPoint: он перенаправит на целевой URL-адрес, если нет аутентификации

person chaoluo    schedule 30.03.2017

Потребуется пользовательский AuthenticationEntryPoint и переопределение метода commence().

Действительно, точка входа должна быть прописана в конфигурации Spring Security.

http.exceptionHandling()
                .authenticationEntryPoint(restAuthenticationEntryPoint)

Образец кода:

public class UserAuthenticationEntryPoint implements
        AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException ex)
            throws IOException, ServletException {
        response.setContentType("application/json");
        response.getOutputStream().print("{\"error\":\"Unauthorized.. Please authenticate..\"}");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }
}
person Muralidharan.rade    schedule 14.11.2017