2011-02-23 8 views
8

ive configuré un manejador de excepción simple en mi aplicación Spring 2.5. Actualmente captura todos Exception sy muestra una página stacktrace.controlador de excepción de primavera para no manejar ciertos tipos de excepción

esto está muy bien, pero ahora surgen de seguridad no patear correctamente la no conectado usuario a la página de inicio de sesión, en lugar de mi página de excepción se muestra con la excepción de seguridad de primavera:

org.springframework.security.AccessDeniedException 

El problema es que esta aplicación no tiene su propia subclase de excepción que utiliza para todas sus excepciones, así que debo mapear Exception pero no asignar AccessDeniedException

¿es esto posible en la primavera 2.5?

edición: con la seguridad de primavera 2.0.1

mi frijol se parece a esto

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 
    <property name="exceptionMappings"> 
     <props> 
      <prop key="java.lang.RuntimeException">common/error</prop> 
     </props> 
    </property> 
</bean>** 
+0

No lo sé, pero también estoy interesado en la solución. – Kartoch

+0

qué versión de seguridad de primavera estás usando? – Ritesh

+0

spring security 2.0.1 – mkoryak

Respuesta

4

La forma en que manejamos esto es tener una clase de resolución de excepciones personalizada que maneje las excepciones que no son detectadas por otros controladores: implementa HandlerExceptionResolver, Ordered.

Declaramos un bean SimpleMappingExceptionResolver separado que capta excepciones específicas.

El pedido es tal que nuestra resolución personalizada se ejecuta después de SimpleMappingExceptionResolver.

El efecto es que las excepciones especificadas (por ejemplo, AccessDeniedException) son manejadas por SimpleMappingExceptionResolver y se dirigen a las páginas apropiadas.

Cualquier otra excepción de tiempo de ejecución la maneja la resolución personalizada, que la reenvía a una página de error genérica.

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 
    <property name="exceptionMappings"> 
     <props> 
      <prop key="org.springframework.security.AccessDeniedException">accessDenied</prop> 
      <prop key="org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException">accessDenied</prop> 
     </props> 
    </property> 
    <property name="order" value="0"/> 
</bean> 

<bean class="package.to.your.handler.DefaultExceptionResolver"> 
    <property name="order" value="1"/> 
</bean> 

Esta disposición permite que usted pueda ponerse tantas excepciones como desee (I Catch 2 aquí, AccessDenied y HibernateOptimisticLockingFailureException) utilizando el sistema de resolución de primavera y todo lo demás es capturado por la resolución personalizada. En la solución aceptada anteriormente, tendría que escribir más código Java para detectar excepciones distintas de AccessDenied.

+0

usted acaba de decir exactamente lo mismo que la solución aceptada, excepto con menos detalles: P – mkoryak

+0

Más detalles editados en mi respuesta. – SteveT

+0

ah gracias por eso – mkoryak

0

Parece que SimpleMappingExceptionHandler tiene una propiedad MappedHandlerClasses que es lo que está buscando, ya que puede acepta un conjunto de excepciones

+0

estas seguro, desde el documento parece que el campo tiene una lista de objetos 'Handler' que manejarán las excepciones mapeadas – mkoryak

2

Sobre la base de la respuesta de Kartoch, en su mapeo tiene un par de opciones. Podría ser más específico en las excepciones que desea atrapar en lugar de RuntimeException, o bien, podría especificar la vista de inicio de sesión para su manejador para AccessDeniedExcpetion. Algo así como redirigir:/login? Err = 401 para el nombre de la vista.

Ver la configuración hecho aquí

http://www.mkyong.com/spring-mvc/spring-mvc-exception-handling-example/

donde tiene varias excepciones manejadas con el café en grano. Haría lo mismo y redirigirá a su vista de inicio de sesión. La única pregunta abierta es si acepta redirigir:/viewname en la configuración, y no estoy en condiciones de probar eso en este momento.

+0

no puedo ser más específico porque la aplicación que heredé ya lanza RunTimeException all sobre el lugar, no puedo ir y cambiarlo en un millón de lugares – mkoryak

+0

Correcto, pensé mucho, por eso incluí la segunda opción. – digitaljoel

7

Una manera de manejar esto es para crear otro controlador de la aplicación de las org.springframework.web.servlet.HandlerExceptionResolver y org.springframework.core.Ordered -interfaces. En su aplicación, se hace algo como lo siguiente:.

public class AccessDeniedExceptionResolver implements HandlerExceptionResolver, Ordered 
{ 
    private int order; 

    @Override 
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) 
    { 
     if(exception instanceof AccessDeniedException) 
     { 
      return new ModelAndView("redirect:/login"); //Replace with redirect to your login-page 
     } 

     return null; //Null-return = pass the exception to next handler in order 
    } 

    public void setOrder(int order) 
    { 
     this.order = order; 
    } 

    @Override 
    public int getOrder() 
    { 
     return order; 
    } 
} 

Ahora, la implementación de la interfaz ordenada le permite indicar el orden de los controladores de excepciones se invocan en el SimpleMappingExceptionResolver implementa la interfaz ordenada también, por lo usted podría hacer algo como siguiente en sus frijol definiciones:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 
    <property name="exceptionMappings"> 
     <props> 
      <prop key="java.lang.RuntimeException">common/error</prop> 
     </props> 
    </property> 
    <property name="order" value="1"/> 
</bean> 

<bean class="package.to.your.handler.AccessDeniedExceptionResolver"> 
    <property name="order" value="0"/> 
</bean> 

el grano de la orden inferior valor tiene mayor prioridad (lo que significa que va a ser invocado ante los que tienen valores más grandes, en este caso AccessDeniedExceptionResolver se invoca antes SimpleMappingEx ceptionResolver.

Espero que esto haya ayudado.

+0

gracias esto funciona .. tengo que esperar 20 horas para darle los puntos. – mkoryak

+0

¿No sería más fácil simplemente agregar otro en SimpleMappingExceptionResolver para AccessDeniedException que correlaciona para redirigir:/login que tener que implementar una clase para hacer esto? – digitaljoel

+0

@mkoryak: Gracias, sin prisas. Una mejor solución también podría aparecer antes de eso, si eso sucede, sin resentimientos;) Además, eche un vistazo a lo que digitaljoel sugiere aquí. – esaj

1

Otra opción más: crear una subclase de SimpleMappingExceptionResolver que sea capaz de excluir ciertas clases de excepción (dejándolas para un procesamiento predeterminado, en su caso Spring Security).

public class ExclusionExceptionResolver extends SimpleMappingExceptionResolver implements InitializingBean { 
    private Class[] excludedClasses; 

    @Override 
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 
    for (Class<?> excludedClass : excludedClasses) { 
     if (excludedClass.isInstance(ex)) { 
     return null; 
     } 
    } 
    return super.doResolveException(request, response, handler, ex); 
    } 
    public void setExcludedClasses(Class[] excludedClasses) { 
    this.excludedClasses = excludedClasses; 
    } 

    @Override 
    public void afterPropertiesSet() throws Exception { 
    if (excludedClasses == null) { 
     excludedClasses = new Class[]{}; 
    } 
    } 
} 
Cuestiones relacionadas