обработчик исключений Spring, чтобы не обрабатывать определенные типы исключений - PullRequest
8 голосов
/ 23 февраля 2011

Я установил простой обработчик исключений в моем приложении Spring 2.5. В настоящее время он перехватывает все Exception s и показывает страницу трассировки стека.

это хорошо, но теперь весенняя защита не правильно пинает незарегистрированного пользователя на страницу входа в систему, вместо этого отображается страница моего исключения с исключением из весенней безопасности:

org.springframework.security.AccessDeniedException

Проблема в том, что у этого приложения нет собственного подкласса Exception, который оно использует для всех своих исключений, поэтому я должен отобразить Exception, но не отобразить AccessDeniedException

это возможно весной 2.5?

edit : с пружинной защитой 2.0.1

мой боб выглядит так

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

Ответы [ 5 ]

7 голосов
/ 25 февраля 2011

Один из способов справиться с этим - создать другой обработчик, реализующий org.springframework.web.servlet.HandlerExceptionResolver и org.springframework.core.Ordered -интерфейс. В своей собственной реализации вы делаете что-то вроде следующего:

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

Теперь реализация Ordered-интерфейса позволяет вам указать порядок, в котором вызываются обработчики исключений. SimpleMappingExceptionResolver также реализует интерфейс Ordered, так что вы можете сделать что-то вроде следующего в ваших определениях bean-компонентов:

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

Компонент со значением порядка LOWER имеет приоритет HIGHER (это означает, что он будет вызываться ДО тех, которые имеют большие значения, в этом случае AccessDeniedExceptionResolver вызывается перед SimpleMappingExceptionResolver.

Надеюсь, это помогло.

4 голосов
/ 28 апреля 2011

Способ, которым мы обрабатываем это, заключается в том, чтобы иметь собственный класс распознавателя исключений, который обрабатывает любые исключения, которые не перехвачены другими обработчиками - он реализует HandlerExceptionResolver, Ordered.

Мы объявляем отдельный компонент SimpleMappingExceptionResolver, который перехватывает определенные исключения.

Порядок таков, что наш пользовательский распознаватель запускается после SimpleMappingExceptionResolver.

В результате указанные исключения (например, AccessDeniedException) обрабатываются SimpleMappingExceptionResolver и направляются на соответствующие страницы.

Любые другие исключения во время выполнения обрабатываются пользовательским распознавателем, который перенаправляет на общую страницу ошибок.

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

Это расположение позволяет вам перехватывать столько исключений, сколько вам нужно (здесь я ловлю 2, AccessDenied и HibernateOptimisticLockingFailureException), используя преобразователь Spring, а все остальное перехватывается пользовательским преобразователем. В принятом выше решении вам придется написать больше кода Java, чтобы перехватывать исключения, отличные от AccessDenied.

2 голосов
/ 25 февраля 2011

Опираясь на ответ Картока, в вашем отображении у вас есть несколько вариантов. Вы могли бы быть более конкретным в исключениях, которые вы хотите перехватить вместо RuntimeException, или вы могли бы указать представление входа в систему для своего обработчика для AccessDeniedExcpetion. Что-то вроде перенаправления: / login? Err = 401 для имени представления.

Смотрите конфигурацию, выполненную здесь

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

Там, где он обрабатывает несколько исключений с одним бином. Вы сделали бы то же самое и перенаправили бы к своему виду входа в систему. Единственный открытый вопрос - если он принимает перенаправление: / viewname в конфигурации, и я не в состоянии проверить это прямо сейчас.

1 голос
/ 18 июня 2012

Еще один вариант: создать подкласс SimpleMappingExceptionResolver, способный исключать определенные классы исключений (оставляя их для обработки по умолчанию, в вашем случае 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[]{};
    }
  }
}
0 голосов
/ 23 февраля 2011

Кажется, что SimpleMappingExceptionHandler имеет свойство MappedHandlerClasses, которое вам нужно, так как оно может принимать набор исключений.

...