IE8显示标准错误页面而不是Spring Security中声明的错误页面

时间:2014-03-06 11:47:03

标签: spring security internet-explorer-8 spring-security custom-error-pages

我已将Spring Security配置为在授权过程中显示自定义错误页面。在Firefox,Opera和Chrome中一切正常,但在IE8中却没有。此浏览器显示403 http代码的默认页面,而不是spring配置文件中定义的一个。我使用预先验证的方案,所以当我检查用户权限时,他或她已经被认证,我只决定是否允许他/她访问所请求的URL。

这是我对web.xml的配置

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

<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Testing realm</realm-name>
</login-config>

<security-role>
    <role-name>*</role-name>
</security-role>

<security-constraint>
    <display-name>free access</display-name>
    <web-resource-collection>
        <web-resource-name>free access pages</web-resource-name>
        <url-pattern>/denied.html</url-pattern>
        <http-method>GET</http-method>
    </web-resource-collection>
</security-constraint>



<!--  only enforce authentication, authorisation performed by application  -->
<security-constraint>
<display-name>restricted access</display-name>
    <web-resource-collection>
        <web-resource-name>All areas</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>*</role-name>
    </auth-constraint>
</security-constraint>

这是我的安全相关配置:

<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
    <sec:filter-chain-map path-type="ant">
        <sec:filter-chain pattern="/**"
            filters="sif,j2eePreAuthFilter,logoutFilter,etf,fsi" />
    </sec:filter-chain-map>
</bean>

<bean id="sif" class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref='preAuthenticatedAuthenticationProvider' />
</sec:authentication-manager>

<bean id="preAuthenticatedAuthenticationProvider"
    class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>

<bean id="preAuthenticatedUserDetailsService"
    class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService" />

<bean id="j2eePreAuthFilter"
    class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
    <property name="authenticationDetailsSource">
        <bean class="pl.company.spring.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSourceFromDatabase">
            <property name="mappableRolesRetriever">
                <bean class="pl.company.spring.DatabaseMappableAttributesRetriever" />
            </property>
            <property name="userRoles2GrantedAuthoritiesMapper">
                <bean class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper">
                    <property name="convertAttributeToUpperCase" value="true" />
                </bean>
            </property>
        </bean>
    </property>
</bean>

<!-- <bean id="preAuthenticatedProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />  -->

<bean id="preAuthenticatedProcessingFilterEntryPoint" class="pl.ivmx.cbp.spring.HTTP403ForbiddenEntryPoint">
    <property name="errorPage" value="/denied.html"/>
</bean>

<bean id="logoutFilter"
    class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg value="/" />
    <constructor-arg>
        <list>
 <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
    </list>
    </constructor-arg>
</bean>

<bean id="servletContext"
    class="org.springframework.web.context.support.ServletContextFactoryBean" />

<bean id="etf" class="org.springframework.security.web.access.ExceptionTranslationFilter">
    <property name="authenticationEntryPoint" ref="preAuthenticatedProcessingFilterEntryPoint" />
 <property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</bean>

<bean id="accessDeniedHandler" class="pl.company.spring.MyAccessDeniedHandlerImpl">
    <property name="errorPage" value="/denied.html"/>
</bean>

<bean id="httpRequestAccessDecisionManager"
    class="org.springframework.security.access.vote.UnanimousBased">
    <property name="allowIfAllAbstainDecisions" value="false" />
<property name="decisionVoters">
    <list>
        <ref bean="roleVoter" />
        <ref bean="permissionVoter"/>
        <ref bean="authenticationVoter"/>
    </list>
</property>
</bean>

<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager" />
<property name="securityMetadataSource">
<sec:filter-invocation-definition-source>
        <! handled by my own voter -->
   <sec:intercept-url pattern="/cbp/rpc/ppecounter*" access="permission_ppecounter"/> 
   <!-- handled by role voter -->
       <sec:intercept-url pattern="/**" access="ROLE_USER" />
   </sec:filter-invocation-definition-source>
</property>
</bean>

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />


<bean id="permissionVoter" class="pl.company.spring.PermissionVoter"/>

<bean id="authenticationVoter" class="org.springframework.security.access.vote.AuthenticatedVoter"/>

<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter" />

我尝试做的是将以下代码段添加到web.xml:

<error-page>
    <error-code>403</error-code>
    <location>/denied.html</location>
</error-page>

但它没有帮助。我还从org.springframework.security.web.access包中检查了AccessDeniedHandlerImpl的代码。由于其handle方法执行转发到自定义错误页面,我检查了响应是否尚未提交:

   public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
        throws IOException, ServletException {
    if (!response.isCommitted()) {
        if (errorPage != null) {
            // Put exception into request scope (perhaps of use to a view)
            request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);

            // Set the 403 status code.
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);

            // forward to error page.
            RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage);
            dispatcher.forward(request, response);
        } else {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
        }
    }
}

我已经覆盖了这个类,并添加了我的自定义日志记录,显示响应尚未提交,并且请求转发到自定义错误页面。

最后一点是ExceptionTranslationFilter使用的Http403ForbiddenEntryPoint类。它的开始方法如下:

public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2) throws IOException,
        ServletException {
    if (logger.isDebugEnabled()) {
        logger.debug("Pre-authenticated entry point called. Rejecting access");
    }
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
}

我也覆盖了这个方法,不发送默认错误页面,但什么都不做。在第二次尝试中,我从AccessDeniedHandlerImpl复制代码以执行转发。 Againt它对IE8没有帮助。 spring数据包的调试日志如下所示:

11:22:37,288 DEBUG [ExceptionTranslationFilter] Access is denied (user is not anonymous); delegating to AccessDeniedHandler
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.UnanimousBased.decide(UnanimousBased.java:90)
at 
11:22:37,289 DEBUG [FilterChainProxy] /denied.html at position 1 of 5 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
11:22:37,289 DEBUG [FilterChainProxy] /denied.html at position 1 of 5 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 2 of 5 in additional filter chain; firing Filter: 'J2eePreAuthenticatedProcessingFilter'
11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 2 of 5 in additional filter chain; firing Filter: 'J2eePreAuthenticatedProcessingFilter'
11:22:37,290 DEBUG [J2eePreAuthenticatedProcessingFilter] Checking secure context token: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@f9fdea61: Principal: org.springframework.security.core.userdetails.User@6038c01: Username: jarek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; []; Not granted any authorities
11:22:37,290 DEBUG [J2eePreAuthenticatedProcessingFilter] Checking secure context token: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@f9fdea61: Principal: org.springframework.security.core.userdetails.User@6038c01: Username: jarek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; []; Not granted any authorities
11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 3 of 5 in additional filter chain; firing Filter: 'LogoutFilter'
11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 3 of 5 in additional filter chain; firing Filter: 'LogoutFilter'
11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 4 of 5 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
 11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 4 of 5 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
 11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 5 of 5 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
11:22:37,290 DEBUG [FilterChainProxy] /denied.html at position 5 of 5 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
11:22:37,290 DEBUG [FilterChainProxy] /denied.html reached end of additional filter chain; proceeding with original chain
11:22:37,290 DEBUG [FilterChainProxy] /denied.html reached end of additional filter chain; proceeding with original chain
11:22:37,290 DEBUG [ExceptionTranslationFilter] Chain processed normally
11:22:37,290 DEBUG [ExceptionTranslationFilter] Chain processed normally
11:22:37,291 DEBUG [HttpSessionSecurityContextRepository] HttpSession being created as SecurityContext is non-default
11:22:37,291 DEBUG [HttpSessionSecurityContextRepository] HttpSession being created as SecurityContext is non-default
11:22:37,291 WARN  [HttpSessionSecurityContextRepository] Failed to create a session, as response has been committed. Unable to store SecurityContext.
11:22:37,291 WARN  [HttpSessionSecurityContextRepository] Failed to create a session, as response has been committed. Unable to store SecurityContext.
11:22:37,291 DEBUG [SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed
11:22:37,291 DEBUG [SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request  processing completed

我也尝试将调度类型添加到Spring过滤器:

<filter-mapping>
    <filter-name>filterChainProxy</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

但IE8再次不愿合作。任何提示如何“强迫”IE8显示/denied.html都会受到欢迎。

1 个答案:

答案 0 :(得分:0)

使错误页面(denied.html)大于512字节。用空格或其他任何方式填充HTML。

在客户端,您可以在Internet设置中禁用“友好错误消息”,IE将显示您的页面,即使它小于512字节。