1. 引言
本文將演示如何在 Spring Security 項目中自定義“訪問被拒絕”頁面。
這可以通過 Spring Security 配置或在 <em >web.xml</em> 文件中的 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,我們可以通過使用 <em>accessDeniedPage()</em> 或 <em>accessDeniedHandler()</em> 方法,在配置 <em>HttpSecurity</em> 元素時,自定義 403 錯誤處理流程。
讓我們創建一個認證配置,將“/admin/**” URL 限制為 <em>ADMIN</em> 角色,並將訪問權限被拒絕頁面設置為我們的自定義 <em>accessDenied.jsp</em> 頁面:
@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. 應用配置
通過定義 <em>error-page</em> 標籤,可以在 Web 應用程序的 <em>web.xml</em> 文件中處理“訪問被拒絕”錯誤。 此標籤包含兩個子標籤:<em>error-code</em>,用於指定要攔截的狀態碼,以及 <em>location</em>,用於指定在遇到錯誤碼時用户將被重定向到的 URL。
<error-page>
<error-code>403</error-code>
<location>/accessDenied</location>
</error-page>如果應用程序沒有 web.xml 文件,如 Spring Boot 的情況,Spring 註解尚不提供與 error-page 標籤完全等效的替代方案。根據 Spring 文檔的説明,在這種情況下,推薦的方法是使用 accessDeniedPage() 和 accessDeniedHandler() 方法,這些方法在第 3 節中進行了介紹。
結論
在本文中,我們詳細介紹瞭如何使用自定義 403 頁來處理訪問權限被拒絕錯誤。