我已将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都会受到欢迎。
答案 0 :(得分:0)
使错误页面(denied.html)大于512字节。用空格或其他任何方式填充HTML。
在客户端,您可以在Internet设置中禁用“友好错误消息”,IE将显示您的页面,即使它小于512字节。