本文介绍了带有SpringSecurity的JSF2:处理@ Secured-Annotation的AccessDeniedException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Spring-Security 3.1.3与Spring 3.2.2和Majorra 2.1.25一起使用.我不使用托管bean,而是使用SpringBeanFacesELResolver.所以基本上,我用spring做所有事情.

我使用以下

<http auto-config="true">
    <form-login login-page="/components/public/login.jsf" authentication-failure-handler-ref="customAuthenticationFailureHandler" />
    <intercept-url pattern="/components/admin/**" access="ROLE_ADMIN" />
    <intercept-url pattern="/components/secured/**" access="ROLE_USER,ROLE_ADMIN" />
    <intercept-url pattern="/**" />
    <session-management>
        <concurrency-control max-sessions="1" expired-url="/components/public/sessionExpired.jsf" />
    </session-management>
    <access-denied-handler ref="customAccessDeniedHandler" />
</http>

可以正常使用,例如在访问安全页面时,将用户定向到登录名,登录后将其带到请求的页面.如果他尝试访问管理页面,但只有ROLE_USER,则我的customAccessDeniedHandler将他定向到拒绝访问的页面

到目前为止,一切都很好.现在的问题如下:我在方法上使用@Secured({ "ROLE_ADMIN" }).如果权限不足的用户访问此方法,则会抛出AccessDeniedException,这正是我想要的. :未调用我的customAccessDeniedHandler!为什么会这样?

更多信息:该方法作为AJAX调用的一部分被调用,我想使用我的处理程序将FacesMessage设置为Feedback.我该如何集中处理?我很确定我可以在此周围包装另一种方法,并使用try-catch自己捕获AccessDeniedException.但是,对于必须保护的每种方法执行此操作,只会使我的代码膨胀,并带有大量不必要的try-catch-method.我如何集中处理异常?

解决方案

我现在找到了一个解决方案.我使用Spring-AOP并将周围"方面绑定"到所有使用@Secured

注释的方法

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

外观看起来像这样

@Service
public class SecurityFeedbackAspect {
    public Object handleSecuredAnnotations(final ProceedingJoinPoint pjp) throws Throwable {
        try {
            return pjp.proceed();
         } catch (AccessDeniedException e) {
            // log + set feedback for user here
         }
    }
}

希望这有一天能对任何人有帮助.一个附加信息:不知何故我无法使它与仅注释配置一起使用,因为@ Secured-check将始终首先被调用,并且只有在Spring-Security-Logic没有引发异常的情况下,我的方面才会运行.我最终使用了XML配置,这似乎总是最重要的,因为我没有找到其他方法(即使使用@Order)

i am using Spring-Security 3.1.3 with Spring 3.2.2 and Majorra 2.1.25. I don't use managed beans, but use SpringBeanFacesELResolver. So basically, i use spring for everything.

I use the following

<http auto-config="true">
    <form-login login-page="/components/public/login.jsf" authentication-failure-handler-ref="customAuthenticationFailureHandler" />
    <intercept-url pattern="/components/admin/**" access="ROLE_ADMIN" />
    <intercept-url pattern="/components/secured/**" access="ROLE_USER,ROLE_ADMIN" />
    <intercept-url pattern="/**" />
    <session-management>
        <concurrency-control max-sessions="1" expired-url="/components/public/sessionExpired.jsf" />
    </session-management>
    <access-denied-handler ref="customAccessDeniedHandler" />
</http>

which works as indended, e.g. on accessing a secured page, the user is directed to the login and after the login he is brought to the requested page. If he tries to reach an admin-page, but only has ROLE_USER, he is directed to the access-denied page by my customAccessDeniedHandler

So far so good. The problem now is the following: i use @Secured({ "ROLE_ADMIN" }) on a method. If a user with insufficient rights accesses this method, an AccessDeniedException is thrown, which is just what i want. BUT: My customAccessDeniedHandler is not invoked! Why is that?

Some more info: The method is invoked as part of an AJAX call and i would like to use my handler to set a FacesMessage as Feedback. How do i do this centrally? I am pretty sure i could wrap another method around this and use try-catch to catch the AccessDeniedException myself. But doing this for every method that has to be secured will just bloat up my code with a massive amount of unnecessary try-catch-methods. How can i handle the Exception centrally?

解决方案

I found a solution now. I use Spring-AOP and "bind" an around aspect to all methods annotated with @Secured

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

The aspect looks like this

@Service
public class SecurityFeedbackAspect {
    public Object handleSecuredAnnotations(final ProceedingJoinPoint pjp) throws Throwable {
        try {
            return pjp.proceed();
         } catch (AccessDeniedException e) {
            // log + set feedback for user here
         }
    }
}

Hope this helps anyone someday. One addition info: Somehow i couldn't get this to work with annotation-only configuration, because the @Secured-check would always be invoked first and my aspect would only run if no exception was thrown by the Spring-Security-Logic. I ended up using XML configuration, which seems to always go first, since i found no other way (even with @Order)

这篇关于带有SpringSecurity的JSF2:处理@ Secured-Annotation的AccessDeniedException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 04:19