Spring 3 Security: AccessDeniedHandler 未被调用

2022-09-03 05:49:28

我有一个弹簧3应用程序,其配置如下。当任何用户尝试访问页面并且他/她没有登录时,我会收到一个访问被拒绝异常,其中包含丑陋的堆栈跟踪。如何处理此异常,而不让它转储堆栈跟踪。我实现了我自己的拒绝访问处理程序,但这不会被调用。

根据所请求资源的类型,我想显示自定义错误消息或页面。这是我的弹簧配置。

我如何让Spring调用我的拒绝访问处理程序。这是我的弹簧配置

 <security:http auto-config='true'>
    <security:intercept-url pattern="/static/**" filters="none"/>
    <security:intercept-url pattern="/login" filters="none"/>

      <security:intercept-url pattern="/**" access="ROLE_USER" />

      <security:form-login login-page="/index"
            default-target-url="/home" always-use-default-target="true"
            authentication-success-handler-ref="AuthenticationSuccessHandler"        
            login-processing-url="/j_spring_security_check" 
            authentication-failure-url="/index?error=true"/>

       <security:remember-me key="myLongSecretCookieKey" token-validity-seconds="1296000" 
            data-source-ref="jdbcDataSource" user-service-ref="AppUserDetailsService" />

       <security:access-denied-handler ref="myAccessDeniedHandler" />   

    </security:http>

    <bean id="myAccessDeniedHandler"
         class="web.exceptions.handlers.AccessDeniedExceptionHandler">
      <property name="errorPage" value="/public/403.htm" />
    </bean>

下面给出了用于处理此异常的自定义类

public class AccessDeniedExceptionHandler implements AccessDeniedHandler
{

    private String errorPage;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException arg2) throws IOException, ServletException {
        response.sendRedirect(errorPage);
    }

       public void setErrorPage(String errorPage) {
       if ((errorPage != null) && !errorPage.startsWith("/")) {
            throw new IllegalArgumentException("errorPage must begin with '/'");
        }
        this.errorPage = errorPage;
    }

}

当我运行此应用程序时,这是我得到的错误。我只粘贴了堆栈跟踪和Spring Debug日志的一部分。

20:39:46,173 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.RoleVoter@5b7da0d1, returned: -1
20:39:46,173 DEBUG AffirmativeBased:53 - Voter: org.springframework.security.access.vote.AuthenticatedVoter@14c92844, returned: 0
20:39:46,178 DEBUG ExceptionTranslationFilter:154 - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:71)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:204)

如何解决此问题?首先,我想阻止春天抛出这个例外。如果它仍然抛出它,我想处理它,而不是举起任何标志。

更新:我也附上了我的网络的一部分.xml。

<!-- Hibernate filter configuration -->

<filter>
        <filter-name>HibernateFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HibernateFilter</filter-name> 
        <url-pattern>/*</url-pattern>       
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

    <!--Dispatcher Servlet -->

   <servlet>
     <servlet-name>rowz</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
   </servlet>

答案 1

在您的配置中,您要求用户在站点上输入任何 URL 时始终进行身份验证:

<security:intercept-url pattern="/**" access="ROLE_USER" />

我认为您应该允许用户在进入登录页面未经身份验证

<security:intercept-url pattern="/your-login-page-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/your-login-process-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/your-login-failure-url" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**" access="ROLE_USER" />

如果您使用类似:的 URL,并且您可以拥有:/login/start/login/error/login/failure

<security:intercept-url pattern="/login/**" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**" access="ROLE_USER" />

更新:

具有此配置应使框架将所有未经身份验证的(匿名)用户重定向到登录页,并使所有用户都经过 AccessDeniedHandler 的身份验证。AccessDeniedException是框架的核心部分之一,忽略它不是一个好主意。如果您只提供Spring Security配置的一部分,则很难提供更多帮助。

请务必阅读 JavaDoc for ExceptionTranslationFilter,详细了解框架会引发哪些异常,以及为什么以及如何处理缺省情况下的异常。

如果可能,请尝试删除您添加的尽可能多的自定义部件,如身份验证成功处理程序RememberMeAuthenticationFilterAccessDeniedHandler,看看问题是否出在哪里?尝试获得最小的累积并逐步添加新功能,以查看错误的来源。

您在问题中没有提到的一件重要事情是此错误消息的结果是什么?你得到吗?或?或者您是否被重定向到登录页面?HTTP 500HTTP 403

如果,正如您在问题中提到的,用户未经身份验证,并且他/她被重定向到登录页面,那么这就是它的工作方式。看起来您收到异常翻译过滤器:172记录的错误消息,只是因为您已将级别设置为Spring Security类。如果是这样,那么这也是它的工作方式,如果您不希望记录错误,那么只需提高Spring Secyruty类的日志记录级别即可。DEBUG

更新 2:

的模式必须与 中设置的 和 属性匹配,以跳过显示登录页面并处理登录的页面上的所有 SpringSecurity 检查。filters="none"login-pagelogin-processing-urlauthentication-failure-ur<security:form-login />

<security:http auto-config='true'>
  <security:intercept-url pattern="/static/**" filters="none"/>
  <security:intercept-url pattern="/index" filters="none"/>
  <security:intercept-url pattern="/j_spring_security_check" filters="none"/>
  <security:intercept-url pattern="/**" access="ROLE_USER" />

  <security:form-login login-page="/index"
        default-target-url="/home" always-use-default-target="true"
        authentication-success-handler-ref="AuthenticationSuccessHandler"        
        login-processing-url="/j_spring_security_check" 
        authentication-failure-url="/index?error=true"/>

   <security:remember-me key="myLongSecretCookieKey" token-validity-seconds="1296000" 
        data-source-ref="jdbcDataSource" user-service-ref="AppUserDetailsService" />

   <security:access-denied-handler ref="myAccessDeniedHandler" />   

</security:http>

答案 2

AccessDeniedHandler在用户登录并且没有资源权限时调用(此处为源)。如果要在用户未登录时处理登录页面的请求,只需在安全上下文中进行配置:

<http ... entry-point-ref="customAuthenticationEntryPoint">

并定义自定义身份验证EntryPoint:

<beans:bean id="customAuthenticationEntryPoint" class="pl.wsiadamy.webapp.controller.util.CustomAuthenticationEntryPoint">
</beans:bean>

提示不要试图与AlexceptionTranslationFilter作斗争。我试图覆盖,没有效果:org.springframework.security.web.access.ExceptionTranslationFilter

<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
  <beans:property name="authenticationEntryPoint"  ref="customAuthenticationEntryPoint"/>
  <beans:property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</beans:bean>
<beans:bean id="accessDeniedHandler"
 class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
  <beans:property name="errorPage" value="/accessDenied.htm"/>
</beans:bean>

只是没有调用。ref="customAuthenticationEntryPoint"


推荐