Spring Security |使用@Secured / @ PreAuthorize进行方法级安全性

时间:2013-05-07 11:15:54

标签: spring security spring-mvc spring-security dwr

我一直在试用这个应用程序的'方法级'安全性,我一直在努力。我们的想法是确保使用DWR从表示层调用的方法。 现在,我尝试在我的方法上添加以下注释:

@PreAuthorize("isAuthenticated() and hasRole('ROLE_CUSTOMER')")

我的安全上下文中的相应条目:

<global-method-security pre-post-annotations="enabled" />

在类似的路线上,我尝试过@Secured注释:

@Secured({"ROLE_CUSTOMER" })

我的安全上下文中的相应条目:

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

理想情况下,我希望如果用户未经过身份验证,则应将其重定向到“登录”页面,并且不应检查“ROLES”。在这种情况下,即使对于未经身份验证的用户,此方法调用也会导致“AccessDeniedException”。在这种情况下,我需要它将用户重定向到登录页面。

为了推进它,我甚至尝试通过创建自定义AccessDenied处理程序来处理访问的异常。不幸的是,处理程序从未被调用,但抛出了异常。

以下是配置:

<access-denied-handler ref="customAccessDeniedHandler"/>

这在同一个文件中定义了相应的处理程序bean。

仍然没有运气。 accessdeniedhandler永远不会被调用。

总结一下这个要求,我需要确保一个方法。如果调用此方法,并且用户未经身份验证,则应将用户重定向到“登录”页面(截至目前,该页面正在抛出Accessdenied execption)。

感谢您的帮助人员..

编辑1 :以下是安全上下文的摘录:

<http>
    <intercept-url pattern="/*sign-in.do*" requires-channel="$secure.channel}" />
    .....
    ..... 
    .....
    <intercept-url pattern="/j_acegi_security_check.do" requires-channel="${secure.channel}" />

    <intercept-url pattern="/*.do" requires-channel="http"  />
    <intercept-url pattern="/*.do\?*" requires-channel="http" />
    <form-login login-page="/sign-in.do" authentication-failure-url="/sign-in.do?login_failed=1"
        authentication-success-handler-ref="authenticationSuccessHandler" login-processing-url="/j_acegi_security_check.do"/>

    <logout logout-url="/sign-out.do" logout-success-url="/index.do" />

    <session-management session-authentication-strategy-ref="sessionAuthenticationStrategy" />
        <access-denied-handler ref="customAccessDeniedHandler"/>
  </http>
    <beans:bean id="customAccessDeniedHandler" class="com.mypackage.interceptor.AccessDeniedHandlerApp"/>

3 个答案:

答案 0 :(得分:0)

我对DWR不太熟悉,但我知道它是一种RPC机制。问题是客户端javascript发送的RPC请求不是导航浏览器的用户发起的常规页面请求。对此类RPC请求的响应不可能使浏览器离开当前页面,因为响应是由您的javascript代码而不是浏览器处理的。

你能做的是:

  1. 实现一种急切的身份验证:在允许用户访问发出DWR(或任何类型的RPC)请求的webapp(URL)之前,将用户重定向到一个简单的.jsp登录页面。
  2. 如果远程过程抛出的AccessDeniedException以某种形式传播到客户端,您可以尝试从javascript代码处理它,例如通过弹出登录对话框,并在一个提交用户的凭据AJAX请求。 (在这种情况下,请确保保存返回的会话ID,并在每次后续请求时将其发回。)

答案 1 :(得分:0)

我有兴趣看到你的security.xml文件的其余部分(具体来说,是<http>元素),因为如果每个用户被拒绝,它会告诉我您有一个<intercept-url>属性,它会覆盖对您的控制器类的调用。如果没有,增加的信息可能有助于解决问题。

假设到目前为止我已离开,另一个可能的错误点可能是指定的access-denied-page本身 - 如果它的路径是受保护的路径(即<intercept-url>),或者它不是'如果指定,您可能会看到您说的错误。

当然,我也不熟悉DWR,所以我显然假设一个标准的Spring MVC框架......

答案 2 :(得分:0)

好的,我没有成功找到为什么会遇到AccessDeniedException。无论如何,我一直在努力,直到找到原因。以下是我采取的几种方法:

1)正如Zagyi所说,我能够将AccessDenied Exception传播到客户端。我可以创建一个异常处理程序并将用户重定向到登录页面。

然而,我采取了一种不同的方法(可能不是最优的方法,但现在似乎有效。这就是我所做的:

1)创建了一个DWRAjaxFilter并仅映射到我感兴趣的远程对象。这样只会对这些远程方法的DWR调用被过滤器拦截。这是因为我不希望所有DWR公开的方法都像登录一样。

   <create creator="spring" javascript="downloadLinksAjaxService">
       <param name="beanName" value="downloadLinksAjaxService" />
       <include method="methodOne" />
       <include method="methodTwo" />  
       <filter class="com.xyz.abc.interceptor.DwrAjaxFilter"></filter>
   </create>

2)以下是实际的过滤器实现:

public class DwrSessionFilter implements AjaxFilter {
    public Object doFilter(final Object obj, final Method method,
            final Object[] params, final AjaxFilterChain chain)
            throws Exception {

        SecurityContext context = SecurityContextHolder.getContext();
        Authentication auth = context.getAuthentication();
        if (!auth.isAuthenticated()
                || auth.getAuthorities().contains(
                        new GrantedAuthorityImpl("ROLE_ANONYMOUS"))) {
            throw new LoginRequiredException("Login Required");
        } else {
            return chain.doFilter(obj, method, params);
        }
    }
}

3)这是客户端处理程序:

function errorHandler(message, exception){

                if(exception && exception.javaClassName == "org.directwebremoting.extend.LoginRequiredException") {

                  document.location.reload();
                }
            }

4)我还为DWR添加了异常映射器,以便将JAVA异常转换为JS异常:

<convert match="java.lang.Exception" converter="exception">
            <param name='include' value='message'/>
        </convert> 

5)这似乎现在效果很好。我还在测试它,看看这是否在某处失败。

不胜感激任何投入。