Saltar al contenido

Manejar excepciones de seguridad en Spring Boot Resource Server

Hola usuario de nuestro sitio, descubrimos la respuesta a lo que estabas buscando, has scroll y la verás más abajo.

Solución:

Como se señaló en comentarios anteriores, el marco de seguridad rechaza la solicitud antes de que llegue a la capa MVC, por lo que @ControllerAdvice no es una opción aquí.

Hay 3 interfaces en el marco Spring Security que pueden ser de interés aquí:

  • org.springframework.security.web.authentication.AuthenticationSuccessHandler
  • org.springframework.security.web.authentication.AuthenticationFailureHandler
  • org.springframework.security.web.access.AccessDeniedHandler

Puede crear implementaciones de cada una de estas interfaces para personalizar la respuesta enviada para varios eventos: inicio de sesión exitoso, inicio de sesión fallido, intento de acceder a recursos protegidos con permisos insuficientes.

Lo siguiente devolvería una respuesta JSON en un intento de inicio de sesión fallido:

@Component
public class RestAuthenticationFailureHandler implements AuthenticationFailureHandler

  @Override
  public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
      AuthenticationException ex) throws IOException, ServletException
  
    response.setStatus(HttpStatus.FORBIDDEN.value());
    
    Map data = new HashMap<>();
    data.put("timestamp", new Date());
    data.put("status",HttpStatus.FORBIDDEN.value());
    data.put("message", "Access Denied");
    data.put("path", request.getRequestURL().toString());
    
    OutputStream out = response.getOutputStream();
    com.fasterxml.jackson.databind.ObjectMapper mapper = new ObjectMapper();
    mapper.writeValue(out, data);
    out.flush();
  

También debe registrar su(s) implementación(es) con el marco de seguridad. En la configuración de Java, esto se parece a lo siguiente:

@Configuration
@EnableWebSecurity
@ComponentScan("...")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter

  @Override
  public void configure(HttpSecurity http) throws Exception
  
    http
       .addFilterBefore(corsFilter(), ChannelProcessingFilter.class)
       .logout()
       .deleteCookies("JESSIONID")
       .logoutUrl("/api/logout")
       .logoutSuccessHandler(logoutSuccessHandler())
       .and()
       .formLogin()
       .loginPage("/login")
       .loginProcessingUrl("/api/login")
       .failureHandler(authenticationFailureHandler())
       .successHandler(authenticationSuccessHandler())
       .and()
       .csrf()
       .disable()
       .exceptionHandling()
       .authenticationEntryPoint(authenticationEntryPoint())
       .accessDeniedHandler(accessDeniedHandler());
  

  /**
   * @return Custom @link AuthenticationFailureHandler to send suitable response to REST clients in the event of a
   *         failed authentication attempt.
   */
  @Bean
  public AuthenticationFailureHandler authenticationFailureHandler()
  
    return new RestAuthenticationFailureHandler();
  

  /**
   * @return Custom @link AuthenticationSuccessHandler to send suitable response to REST clients in the event of a
   *         successful authentication attempt.
   */
  @Bean
  public AuthenticationSuccessHandler authenticationSuccessHandler()
  
    return new RestAuthenticationSuccessHandler();
  

  /**
   * @return Custom @link AccessDeniedHandler to send suitable response to REST clients in the event of an attempt to
   *         access resources to which the user has insufficient privileges.
   */
  @Bean
  public AccessDeniedHandler accessDeniedHandler()
  
    return new RestAccessDeniedHandler();
  

En caso de que estés usando @EnableResourceServertambién puede encontrar conveniente extender ResourceServerConfigurerAdapter en lugar de WebSecurityConfigurerAdapter en tus @Configuration clase. Al hacer esto, simplemente puede registrar una cuenta personalizada AuthenticationEntryPoint anulando configure(ResourceServerSecurityConfigurer resources) y usando resources.authenticationEntryPoint(customAuthEntryPoint()) dentro del método.

Algo como esto:

@Configuration
@EnableResourceServer
public class CommonSecurityConfig extends ResourceServerConfigurerAdapter 

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception 
        resources.authenticationEntryPoint(customAuthEntryPoint());
    

    @Bean
    public AuthenticationEntryPoint customAuthEntryPoint()
        return new AuthFailureHandler();
    

También hay un bonito OAuth2AuthenticationEntryPoint que se puede ampliar (ya que no es definitivo) y reutilizar parcialmente al implementar un personalizado AuthenticationEntryPoint. En particular, agrega encabezados “WWW-Authenticate” con detalles relacionados con el error.

No puede utilizar las anotaciones del controlador de excepciones Spring MVC como @ControllerAdvice porque los filtros de seguridad de Spring se activan mucho antes que Spring MVC.

Más adelante puedes encontrar las interpretaciones de otros gestores de proyectos, tú asimismo tienes la habilidad dejar el tuyo si te gusta.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *