Как установить авторизацию на уровне просмотра в Vaadin

Я использую Vaadin 7, Spring Security и надстройку Spring-Vaadin-Integration и настроил бит аутентификации, чтобы он работал как шарм. Когда я добрался до части авторизации, у меня возникла неприятная проблема. Я хочу установить авторизацию для каждого представления без необходимости проверять авторизацию на уровне навигации (как в надстройке AppFoundation).

Итак, я хочу что-то вроде этого:

@Component
@Scope("prototype")
@VaadinView(value = ASecuredView.NAME, cached = true)
@Secured("ROLE_ADMIN_PROD")
public class ASecuredView extends GridLayout implements View {
    ...
}

Когда неавторизованный пользователь пытается войти в это представление, я хочу обработать AccessDeniedException и представить пользователю уведомление, в котором что-то объясняется в строках «Представление доступно только администраторам».

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

Проблема в том, что я не могу поймать AccessDeniedException.

Я пробовал несколько разных методов решения этой проблемы, но безрезультатно. Вот некоторые из них:

  • Я создал CustomAccessDeniedHandler, никаких исключений не обнаружено.
  • Я пробовал использовать простой тег access-denied-handler, но исключение все еще не обнаружено.
  • Я попытался «повторно выбросить» исключение с помощью org.springframework.web.servlet.handler.SimpleMappingExceptionResolver, но все еще с таким же поведением.
  • Я попробовал аннотацию @PreFilter, но это не сработало.
  • Я пробовал использовать аспект handleSecuredAnnotations (около), но даже это не сработало!

Я неправильно подхожу к этому?

Может быть, есть более простой / лучший способ добиться этого? Как?

Вот мой файл spring -security.xml. Я предоставлю весь шабанг. Обратите внимание, что я также пробовал разные методы по отдельности:

<global-method-security secured-annotations="enabled" />

<!-- Spring-Security -->
<http auto-config="true" use-expressions="true" disable-url-rewriting="true">
    <form-login authentication-success-handler-ref="authenticationSuccessHandler" />
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <logout success-handler-ref="logoutSuccessHandler" invalidate-session="true" logout-url="/logout" />
    <access-denied-handler ref="customAccessDeniedHandler" />
</http>

<authentication-manager>
    <authentication-provider ref="activeDirectoryAuthenticationProvider" />
</authentication-manager>

<beans:bean id="activeDirectoryAuthenticationProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <beans:constructor-arg value="someserver.com" />
    <beans:constructor-arg value="ldap://ldaplb.someserver.com:389" />
    <beans:property name="userDetailsContextMapper" ref="customUserDetailsContextMapper" />
    <beans:property name="convertSubErrorCodesToExceptions" value="true" />
</beans:bean>

<beans:bean id="customAccessDeniedHandler" class="com.some.path.web.CustomAccessDeniedHandler" />
<beans:bean id="customUserDetailsContextMapper" class="com.some.path.web.CustomUserDetailsContextMapper" />

<beans:bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <beans:property name="defaultErrorView" value="uncaughtException" />
    <beans:property name="excludedExceptions" value="org.springframework.security.access.AccessDeniedException" />

    <beans:property name="exceptionMappings">
        <beans:props>
            <beans:prop key=".DataAccessException">dataAccessFailure</beans:prop>
            <beans:prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</beans:prop>
            <beans:prop key=".TypeMismatchException">resourceNotFound</beans:prop>
            <beans:prop key=".MissingServletRequestParameterException">resourceNotFound</beans:prop>
        </beans:props>
    </beans:property>
</beans:bean>

<aop:config>
    <aop:aspect id="securedAspect" ref="securityFeedbackAspect">
        <aop:around pointcut="@annotation(org.springframework.security.access.annotation.Secured)" method="handleSecuredAnnotations" />
    </aop:aspect>
</aop:config>

person Roger    schedule 14.03.2014    source источник


Ответы (1)


В итоге я реализовал ErrorHandler в классе MainUI. Я уверен, что есть способы лучше решить эту проблему, но я не нашел ни одного.

public class MainUI extends UI implements ErrorHandler {
    private static final long serialVersionUID = 1L;

    @Override
    protected void init(VaadinRequest request) {
        VaadinSession.getCurrent().setErrorHandler(this);
        @SuppressWarnings("unused")
        DiscoveryNavigator navigator = new DiscoveryNavigator(this, this);
    }

    @Override
    public void error(com.vaadin.server.ErrorEvent event) {

        if (event.getThrowable() instanceof AccessDeniedException) {
            AccessDeniedException accessDeniedException = (AccessDeniedException) event.getThrowable();
            Notification.show(accessDeniedException.getMessage(), Notification.Type.ERROR_MESSAGE);
            getUI().getNavigator().navigateTo(FirstView.NAME);
            return;
        }
        // connector event
        if (event.getThrowable().getCause().getCause().getCause() instanceof AccessDeniedException) {
            AccessDeniedException accessDeniedException = (AccessDeniedException) event.getThrowable().getCause().getCause().getCause();
            Notification.show(accessDeniedException.getMessage(), Notification.Type.ERROR_MESSAGE);
            getUI().getNavigator().navigateTo(FirstView.NAME);
            return;
        }
    }
}
person Roger    schedule 18.03.2014