如何使用Spring Security 3.0.x处理HTTP 403

时间:2010-11-15 16:44:29

标签: security spring spring-security

我在使用Spring Security 3.0.x时遇到了一个小问题(特别是3.0.2)。我正在处理的整个应用程序工作正常,除非有权限的人试图登录。

当它发生时,用户被重定向到“欢迎”页面,因为他的用户名/密码有效,并且他收到一个可爱的白页,其中包含:“错误403:访问被拒绝”

所以,我一直在网上试图找到如何处理这种行为。到目前为止,我已经得出结论,如果我错了,请纠正我,它由ExceptionTranslationFilter管理。但我不太明白如何善用这些信息。

我已经尝试编辑我的SecurityContext.xml,将 access-denied-handler 标记添加到我的 http 标记中,但它不起作用。我是否需要添加超过此标签才能使其正常工作?还有其他可能性使我的应用程序更加用户友好吗?

修改:我想重定向到一个页面,例如,让我们说403.html。

真诚地,
感谢

5 个答案:

答案 0 :(得分:22)

我仍然不明白为什么你必须实现自己的访问处理程序......我目前面临同样的任务:

 <security:access-denied-handler error-page="/accessDenied"/> - works like charm.

不要忘记在Controller中指定处理程序:

 @RequestMapping(value = "/accessDenied")
      public String accessDenied() {

            return "accessDenied"; // logical view name
       }

Spring Boot更新(2014年10月):

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling().accessDeniedHandler(customHandler) OR .accessDeniedPage("/somePage.html").and
            .formLogin()
                .failureHandler(ajaxAuthenticationFailureHandler)} 

现在我们并没有真正为这样的任务返回视图,因为angular js会启动,所以你可以使用你的失败/成功处理程序并返回定制的JSON响应。对我们来说,使用失败处理程序就足够了,但是您可以选择控件的位置。我们通常不使用视图解析器,因为有一些UI切片框架(例如角度分割)能够将碎片构建到单个页面中为了你。 Html片段存储在服务器上,只是作为静态资源提供。

让我们使用嵌入式Tomcat实现与web.xml类似的行为!

@Configuration
@EnableAutoConfiguration
public class ApplicationWebXml extends SpringBootServletInitializer {

private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.profiles(addDefaultProfile())
            .showBanner(false)
            .sources(Application.class);
}

//required for container customizer to work, the numerous tutorials didn't work for me, so I simply tried overriding the default one
@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
    return tomcat;
}

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer(

) {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
             containerFactory.setSessionTimeout(1); // just for your interest, remove as necessary

            containerFactory.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN,"/views/accessDenied.html"),
                    new ErrorPage(HttpStatus.NOT_FOUND,"/views/notFound.html"));
            containerFactory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
                @Override
                public void customize(Connector connector) {
                    connector.setPort(8082);// just for your interest, remove as necessary
                }
            });
        }
    };
}

}

答案 1 :(得分:9)

处理错误重定向的更简洁方法是使用web.xml中的<error-page><error-code>标记。请参阅下面的示例:

<!-- Custom 403 Error Page -->
<!--
            NOTE: Security will throw this error when a user has been authenticated successfully
            but lacks the permissions to perform the requested action.
    -->
    <error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>

只要遇到指定的错误代码,此代码块就会重定向到指定的位置。

这样就无需在应用程序逻辑中使用授权代码。

答案 2 :(得分:8)

我发现了如何做到这一点。通过实现AccessDeniedHandler接口和相应的句柄方法,我可以轻松地控制Http 403错误的处理方式。

这样,您可以在会话中添加各种项目,然后在jsp上拦截它们。

然后xml文件如下所示:

<sec:http>
    <!-- lots of urls here -->
    <sec:access-denied-handler ref="accessDeniedHandler" />
    <sec:anonymous/>
</sec:http>

<bean id="accessDeniedHandler" class="foo.bar.CustomAccessDeniedHandler">
    <property name="accessDeniedUrl" value="403.html" />
</bean>

java类:

package foo.bar;
public class CustomAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
private String accessDeniedUrl;

    public CustomAccessDeniedHandler() {
    }

    public CustomAccessDeniedHandler(String accessDeniedUrl) {
        this.accessDeniedUrl = accessDeniedUrl;
    }

    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.sendRedirect(accessDeniedUrl);
        request.getSession().setAttribute("CustomSessionAttribute", "value here");
    }

    public String getAccessDeniedUrl() {
        return accessDeniedUrl;
    }

    public void setAccessDeniedUrl(String accessDeniedUrl) {
        this.accessDeniedUrl = accessDeniedUrl;
    }
}

一个jsp示例:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <c:if test="${!empty CustomSessionAttribute}">
    <br/>
    ACCESS IS DENIED
    <br/>
 </c:if>
<!-- other stuff down here -->

答案 3 :(得分:3)

使这项工作的方法是在入口点定义一个处理程序:

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException {

        if (authException != null) {
            // you can check for the spefic exception here and redirect like this
            response.sendRedirect("403.html");
        }
    }
}

您可以通过将此设置为xml配置文件中的入口点来将其定义为入口点:

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

  ...

</http>

答案 4 :(得分:1)

您已经检查了应用程序中的标记,对我来说它似乎有效。

<sec:access-denied-handler error-page="/handle403Url" />

我想调用handle403Url来处理此错误(例如显示错误)。

不要忘记您必须在过滤器中允许此URL,以便此用户权限可以访问它,因此在flters的开头您必须添加以下内容:

<sec:intercept-url pattern="/handle403Url" filters="none" />