1. 概述
本文将展示如何在Spring Security项目中自定义访问被拒绝页面。这可以通过Spring Security配置或在web.xml
文件中的Web应用程序配置来实现。接下来的章节将详细介绍这两种方法。
2. 自定义JSP
当用户尝试访问他们没有权限的页面时,应用会返回403状态码,表示访问被拒绝。为了用自定义页面替换默认的Spring 403状态响应页面,首先需要创建一个名为accessDenied.jsp
的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配置
默认情况下,Spring Security有一个ExceptionTranslationFilter
,它处理AuthenticationException
和AccessDeniedException
类型的异常。后者通过accessDeniedHandler
属性来完成,它使用AccessDeniedHandlerImpl
类。
为了定制这种行为,使其使用我们之前创建的自定义页面,我们需要覆盖ExceptionTranslationFilter
类的属性。这可以通过Java配置或XML配置来实现。
3.1. 访问被拒绝页面
使用Java,可以通过httpSecurity
元素的accessDeniedPage()
或accessDeniedHandler()
方法自定义403错误处理过程。
让我们创建一个限制"/admin/*"
URL对ADMIN
角色的认证配置,并将访问被拒绝页面设置为我们刚才创建的accessDenied.jsp
:
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
// ...
.and()
.exceptionHandling().accessDeniedPage("/accessDenied.jsp");
}
对应的XML配置如下:
<http use-expressions="true">
<access-denied-handler error-page="/accessDenied"/>
</http>
3.2. 访问被拒绝处理器
使用访问被拒绝处理器而不是页面的优点是可以定义在重定向到403页面之前执行的自定义逻辑。为此,我们需要创建一个实现AccessDeniedHandler
接口的类,并重写handle()
方法。
让我们创建一个自定义的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");
}
}
在安全配置中,我们将定义bean并设置自定义的AccessDeniedHandler
:
@Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
//...
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
如果要使用XML配置上述CustomAccessDeniedHandler
类,配置会有所不同:
<bean name="customAccessDeniedHandler"
class="com.baeldung.security.CustomAccessDeniedHandler" />
<http use-expressions="true">
<access-denied-handler ref="customAccessDeniedHandler"/>
</http>
4. 应用程序配置
处理访问被拒绝错误可以通过Web应用程序的web.xml
文件来完成,通过定义error-page
标签。这个标签包含两个子标签:error-code
指定要拦截的状态码,location
指定了在遇到错误代码时用户将被重定向到的URL:
<error-page>
<error-code>403</error-code>
<location>/accessDenied</location>
</error-page>
如果应用程序没有web.xml
文件,如Spring Boot的情况,Spring注解目前还没有提供与error-page
标签精确对应的替代方案。根据Spring文档的建议,在这种情况下,应使用第3部分中介绍的accessDeniedPage()
和accessDeniedHandler()
方法。
5. 总结
在这篇简短的文章中,我们详细介绍了如何使用自定义的403页面处理访问被拒绝错误的各种方式。文章的完整源代码可以在GitHub项目中找到。