Spring Security – Customize the 403 Forbidden/Access Denied Page – Spring Security – 自定义 403 Forbidden/Access Denied 页面

最后修改: 2017年 2月 14日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this article, we will show how to customize the access denied page in a Spring Security project.

在这篇文章中,我们将展示如何在Spring Security项目中定制拒绝访问的页面

This can be achieved either through the Spring Security configuration or web application configuration in the web.xml file.

这可以通过Spring Security配置或web.xml文件中的Web应用配置来实现。

In the remaining sections, we will take a more in-depth look at each of these options.

在剩下的章节中,我们将更深入地研究这些选项中的每一个。

2. Custom JSP

2.自定义JSP

Whenever a user attempts to access a page that is restricted to roles they do not have, the application will return a status code of 403, which means Access Denied.

每当用户试图访问一个限制他们没有的角色的页面时,应用程序将返回一个403的状态代码,这意味着拒绝访问

In order to replace the Spring 403 status response page with a custom one, let’s first create a JSP file called accessDenied.jsp:

为了用一个自定义的页面取代Spring的403状态响应,我们首先创建一个JSP文件,名为accessDenied.jsp

<body>
<h2>Sorry, you do not have permission to view this page.</h2>

Click <a href="<c:url value="/homepage.html" /> ">here</a>
to go back to the Homepage.
</body>

3. Spring Security Configuration

3.Spring安全配置

By default, Spring Security has an ExceptionTranslationFilter defined which handles exceptions of type AuthenticationException and AccessDeniedException. The latter is done through a property called accessDeniedHandler, which uses the AccessDeniedHandlerImpl class.

默认情况下,Spring Security定义了一个ExceptionTranslationFilter,它处理AuthenticationExceptionAccessDeniedException类型的异常。后者是通过一个名为accessDeniedHandler的属性完成的,它使用了AccessDeniedHandlerImpl类。

In order to customize this behavior to use our own page that we created above, we need to override the properties of the ExceptionTranslationFilter class. This can be done through either Java configuration or XML configuration.

为了自定义这一行为,使用我们上面创建的自己的页面,我们需要覆盖ExceptionTranslationFilter类的属性。这可以通过Java配置或XML配置来完成。

3.1. Access Denied Page

3.1.拒绝访问的页面

Using Java, we can customize the 403 error handling process by using the accessDeniedPage() or accessDeniedHandler() methods while configuring the HttpSecurity element.

使用Java,我们可以通过使用accessDeniedPage()accessDeniedHandler()方法自定义403错误处理过程,同时配置HttpSecurity元素。

Let’s create an authentication configuration that restricts the “/admin/**” URLs to the ADMIN role and sets the access denied page to our custom accessDenied.jsp page:

让我们创建一个认证配置,将“/admin/**“URL限制给ADMIN角色,并将拒绝访问的页面设置为我们自定义的accessDenied.jsp页面。

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
      // ...
      .and()
      .exceptionHandling().accessDeniedPage("/accessDenied.jsp");
}

Let’s take a look at the equivalent XML configuration for the access denied page:

让我们看一下拒绝访问页面的等效XML配置。

<http use-expressions="true">
    <access-denied-handler error-page="/accessDenied"/>
 </http>

3.2. Access Denied Handler

3.2.拒绝访问的处理程序

Using an access denied handler instead of a page has the advantage that we can define custom logic to be executed before redirecting to the 403 page. For this, we need to create a class that implements the AccessDeniedHandler interface and overrides the handle() method.

使用一个访问拒绝处理程序而不是一个页面的好处是,我们可以定义自定义逻辑,在重定向到403页面之前执行。为此,我们需要创建一个实现AccessDeniedHandler接口的类并重写handle()方法。

Let’s create a custom AccessDeniedHandler class that logs a warning message for every access denied attempt containing the user that made the attempt and the protected URL they were trying to access:

让我们创建一个自定义的AccessDeniedHandler类,为每一个访问被拒绝的尝试记录一条警告信息,其中包含进行尝试的用户和他们试图访问的受保护URL。

public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    public static final Logger LOG
      = Logger.getLogger(CustomAccessDeniedHandler.class);

    @Override
    public void handle(
      HttpServletRequest request,
      HttpServletResponse response, 
      AccessDeniedException exc) throws IOException, ServletException {
        
        Authentication auth 
          = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            LOG.warn("User: " + auth.getName() 
              + " attempted to access the protected URL: "
              + request.getRequestURI());
        }

        response.sendRedirect(request.getContextPath() + "/accessDenied");
    }
}

In the security configuration, we’ll define the bean and set the custom AccessDeniedHandler:

在安全配置中,我们将定义Bean并设置自定义AccessDeniedHandler

@Bean
public AccessDeniedHandler accessDeniedHandler(){
    return new CustomAccessDeniedHandler();
}

//...
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());

If we want to configure the CustomAccessDeniedHandler class defined above using XML, the configuration will look slightly different:

如果我们想用XML来配置上面定义的CustomAccessDeniedHandler类,配置看起来会略有不同。

<bean name="customAccessDeniedHandler" 
  class="com.baeldung.security.CustomAccessDeniedHandler" />

<http use-expressions="true">
    <access-denied-handler ref="customAccessDeniedHandler"/>
</http>

4. Application Configuration

4.应用配置

Handling the access denied error can be done through the web.xml file of a web application, by defining an error-page tag. This contains two subtags called error-code, which specifies the status code to be intercepted, and location, which signifies the URL to which the user will be redirected in case the error code is encountered:

处理拒绝访问的错误可通过 Web 应用程序的 web.xml 文件完成,方法是定义一个 error-page 标签。该标签包含两个子标签,名为error-code,,它指定了要拦截的状态代码,以及location,,它标志着用户在遇到错误代码时将被重定向到的URL。

<error-page>
    <error-code>403</error-code>
    <location>/accessDenied</location>
</error-page>

If an application does not have a web.xml file, as is the case with Spring Boot, the Spring annotations do not currently provide an exact alternative to the error-page tag. According to the Spring documentation, in this case, the recommended approach is to use the methods accessDeniedPage() and accessDeniedHandler() presented in section 3.

如果应用程序没有web.xml文件,如Spring Boot的情况,Spring注解目前没有提供error-page标签的确切替代方法。根据Spring文档,在这种情况下,推荐的方法是使用第3节中介绍的方法accessDeniedPage()accessDeniedHandler()

5. Conclusion

5.结论

In this quick article, we have detailed the various ways that an access denied error can be handled using a custom 403 page.

在这篇快速文章中,我们已经详细介绍了使用自定义403页面处理拒绝访问错误的各种方法。

The complete source code of the article can be found in the GitHub project.

文章的完整源代码可以在GitHub项目中找到。