Пользовательская аутентификация / авторизация / ответы OAuth2 - Spring Security - PullRequest
0 голосов
/ 14 апреля 2020

Итак, я создал свой собственный сервер авторизации для своего приложения. Он также играет роль сервера ресурсов, просто для тестирования в данный момент.

Для согласованности я хотел бы настроить ответы как для конечных точек OAuth2 (сбой запроса токена - например, ошибка аутентификации), так и для конечных точек сервера ресурсов (ошибки авторизации). В Интернете я видел различные ресурсы, в которых упоминалось создание пользовательского AuthenticationEntryPoint или ExceptionTranslator, но ни один из них не работал для меня.

Это модель ApiError:

public class ApiError {

    private List<String> errors = new ArrayList<>();
    private LocalDateTime timestamp;
    private Cause cause;
    private HttpResponseStatus httpResponseStatus;

    //constructors, getters, setters

    private class HttpResponseStatus {

        private int value;
        private String message;

        public HttpResponseStatus(HttpStatus httpStatus) {
            this.value = httpStatus.value();
            this.message = httpStatus.getReasonPhrase();
        }

        public int getValue() {
            return value;
        }

        public String getMessage() {
            return message;
        }
    }

    private class Cause {

        private String exception;
        private String message;

        public Cause(Class<?> exception, String message) {
            this.exception = exception.getSimpleName();
            this.message = message;
        }

        public String getException() {
            return exception;
        }

        public String getMessage() {
            return message;
        }
    }
}

Вот мой AuthenticationEntryPoint. Я попытался поместить его в WebSecurityConfigurerAdapter конфигурацию ниже, но это не сработало:

@Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
                         AuthenticationException e) throws IOException, ServletException {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpStatus httpStatus = HttpStatus.UNAUTHORIZED;
        ApiError apiError = new ApiError(httpStatus, e, "Authentication error");
        String jsonResponse = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(apiError);

        httpServletResponse.setStatus(httpStatus.value());
        httpServletResponse.getOutputStream().print(jsonResponse);
    }

Вот тип ответов Spring Security по умолчанию, которые я хотел бы изменить:

{
  "error": "unauthorized",
  "error_description": "Full authentication is required to access this resource"
}
{
  "error": "invalid_token",
  "error_description": "Invalid access token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleAiOjE1ODY4NjkyOTYsInVzZXJfbmFtZSI6ImFkaXBvcEBnbWFpbC5jb20iLCJhdXRob3JpdGllcyI6WyJST0xFX01BTkFHRVIiXSwianRpIjoiNGYxZmQ1NTItYmQxNC00NDcyLWJhOTctNjIxY2FlZmYzNGQxIiwiY2xpZW50X2lkIjoic2FmZWRyaXZlLXdlYmFwcCIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdfQ.IMCogr_M8Skw0R0g0pqshROh8-nms8U3zt5i1G7CXO48OcJ76V1WXTGizn5anzFFIRHk0xGhw-r46lgHhLoWB89pjCC04PAIjFwl31flKWVSW6js9QfMt4O8CL6TAXnyHShUyJxbLZnnavTL3b40iLOHNJSeIf7Ed6goqOZMwZUBDB2KKCY_rmu80Ntj69uzVBrVfXCdDW7SRy-05uTqIGlBTWf3v4NZ4lV7EYzTJOcjavkBcSJeLcNi0DpYu1enF4rLPP9MeIUdiWT9sD6FOlLjs_vXQ_rZnxj-TVVkGSYRNn4u3-Znx4WZ3QBbcDU_O_w8qrp5_JnQbXy27-fmpg"
}
{
  "error": "invalid_grant",
  "error_description": "Bad credentials"
}

Вот как мой WebSecurityConfigurerAdapter (общая конфигурация безопасности c - заказ 1 , AuthenticationManager настроен в другой WebSecurityConfigurerAdapter с заказ 100 ) выглядит так:

@Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf().disable()
                .headers().frameOptions().disable()
                .and()
                .antMatcher("/console/**")
                .authorizeRequests()
                .antMatchers("/console/**").hasRole("ADMIN")
                .and()
                .httpBasic();
    }

ResourceServerConfigurerAdapter:

@Override
    public void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .authorizeRequests()
                    .antMatchers("/actuator/**", "/api-docs/**").permitAll()
                    .antMatchers("/protected/**").hasAnyRole("ADMIN", "MANAGER")
                .anyRequest().authenticated();
    }

AuthorizationServerConfigurerAdapter:

@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        //enables chaining multiple types of claims containing different information
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenConverter));

        endpoints.tokenStore(tokenStore)
                .accessTokenConverter(tokenConverter)
                .authenticationManager(authenticationManager)
                .tokenEnhancer(tokenEnhancerChain);
    }

Как мне это настроить? Я просмотрел бесчисленные ресурсы. Какой HttpSecurity имеет приоритет? Я немного смущен.

...