2016-01-12 17 views
6

La mia autenticazione è basata su spring-boot-security-example. Quando inserisco un token non valido, vorrei lanciare un'eccezione 401 non autorizzata. Tuttavia, ottengo sempre una risorsa 404 non trovata. La mia configurazione imposta una gestione delle eccezioni ma viene ignorata, probabilmente perché il mio AuthenticationFilter è stato aggiunto in precedenza e la richiesta non raggiunge il gestore delle eccezioni.Spring Boot Security non lancia 401 Exception non autorizzata ma 404 non trovata

Cosa avrei bisogno di cambiare per lanciare invece le eccezioni 401?

ho un filtro di autenticazione:

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; 
} 

un'implementazione 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")); 
} 

... 

} 

ed una configurazione che appare come segue:

@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); 
} 
} 

risposta

5

ho trovato la risposta in questa discussione: Return HTTP Error 401 Code & Skip Filter Chains

Invece di

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

ho bisogno di chiamare

httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 

Sembra che la catena si ferma quando non continuare chiamandolo e impostando lo stato su un codice diverso - l'eccezione viene generata correttamente

6

ho risolto aggiungendo la seguente annotazione sulla classe @SpringBootApplication di primo livello:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class}) 

È possibile che Spring Boot non riesca a trovare la pagina di errore predefinita?

+0

Un fortunatamente questo non funziona Non uso la parte MVC di spring-boot – Frame91

Problemi correlati