2016-01-12 16 views
6

Moje uwierzytelnienie jest oparte na spring-boot-security-example. Po wprowadzeniu nieważnego tokena chciałbym rzucić 401 nieautoryzowany wyjątek. Zawsze jednak zamiast tego pojawia się zasób 404. Moja konfiguracja ustawia obsługę wyjątków, ale jest ignorowana - prawdopodobnie dlatego, że mój filtr uwierzytelniania został dodany wcześniej, a żądanie nie dotrze do mojej procedury obsługi wyjątku.Spring Boot Security nie wyrzuca 401 nieautoryzowanego wyjątku, ale 404 nie znaleziono

Co trzeba zmienić, aby zamiast tego podać 401 wyjątków?

Mam filtr uwierzytelniania:

public class AuthenticationFilter extends GenericFilterBean { 

... 

@Override 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
    HttpServletRequest httpRequest = asHttp(request); 
    HttpServletResponse httpResponse = asHttp(response); 
    Optional<String> token = Optional.fromNullable(httpRequest.getHeader("X-Auth-Token")); 

    try { 
     if (token.isPresent()) { 
      logger.debug("Trying to authenticate user by X-Auth-Token method. Token: {}", token); 
      processTokenAuthentication(token); 
      addSessionContextToLogging(); 
     } 

     logger.debug("AuthenticationFilter is passing request down the filter chain"); 
     chain.doFilter(request, response); 
    } catch (InternalAuthenticationServiceException internalAuthenticationServiceException) { 
     SecurityContextHolder.clearContext(); 
     logger.error("Internal authentication service exception", internalAuthenticationServiceException); 
     httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 
    } catch (AuthenticationException authenticationException) { 
     SecurityContextHolder.clearContext(); 
     httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage()); 
    } finally { 
     MDC.remove(TOKEN_SESSION_KEY); 
     MDC.remove(USER_SESSION_KEY); 
    } 
} 

private void addSessionContextToLogging() { 
    ... 
} 

... 

private void processTokenAuthentication(Optional<String> token) { 
    Authentication resultOfAuthentication = tryToAuthenticateWithToken(token); 
    SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication); 
} 

private Authentication tryToAuthenticateWithToken(Optional<String> token) { 
    PreAuthenticatedAuthenticationToken requestAuthentication = new PreAuthenticatedAuthenticationToken(token, null); 
    return tryToAuthenticate(requestAuthentication); 
} 

private Authentication tryToAuthenticate(Authentication requestAuthentication) { 
    Authentication responseAuthentication = authenticationManager.authenticate(requestAuthentication); 
    if (responseAuthentication == null || !responseAuthentication.isAuthenticated()) { 
     throw new InternalAuthenticationServiceException("Unable to authenticate Domain User for provided credentials"); 
    } 
    logger.debug("User successfully authenticated"); 
    return responseAuthentication; 
} 

implementacja AuthenticationProvider:

@Provider 
public class TokenAuthenticationProvider implements AuthenticationProvider { 

@Override 
public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
    Optional<String> token = (Optional) authentication.getPrincipal(); 
    if (!token.isPresent() || token.get().isEmpty()) { 
     throw new BadCredentialsException("No token set."); 
    } 
    if (!myCheckHere()){ 
     throw new BadCredentialsException("Invalid token"); 
    } 

    return new PreAuthenticatedAuthenticationToken(myConsumerObject, null, AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_API_USER")); 
} 

... 

} 

i konfiguracja, która wygląda następująco:

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http. 
      csrf().disable(). 
      sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS). 
      and(). 
      anonymous().disable(). 
      exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint()); 

    http.addFilterBefore(new AuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class); 
} 


@Override 
protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth.authenticationProvider(tokenAuthenticationProvider()); 
} 


@Bean 
public AuthenticationProvider tokenAuthenticationProvider() { 
    return new TokenAuthenticationProvider(); 
} 

@Bean 
public AuthenticationEntryPoint unauthorizedEntryPoint() { 
    return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED); 
} 
} 

Odpowiedz

5

Znalazłem odpowiedź w tym wątku: Return HTTP Error 401 Code & Skip Filter Chains

Zamiast

httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage()); 

Muszę zadzwonić

httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 

Wydaje się, że łańcuch zatrzyma się, kiedy nie kontynuować wywoływanie go i ustawianie statusu na inny kod - wyjątek jest generowany poprawnie

6

Rozwiązałem go poprzez dodanie następujących adnotacja na moim najwyższym poziomie @SpringBootApplication klasa:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class}) 

Czy Spring Boot może mieć problem ze znalezieniem domyślnej strony błędu?

+0

Un na szczęście to nie działa. Nie używam części sprężynowej MVC – Frame91