Spring Security異常處理
Spring Security在Filter chain中使用ExceptionTranslationFilter檢查并處理在認(rèn)證和授權(quán)過程中拋出的異常。該Filter支持處理或者分發(fā)三種常規(guī)異常行為:
- 未認(rèn)證拋出的AuthenticationException继效,定向到用戶登錄界面
- 未授權(quán)拋出的AccessDeniedException脾还,定向到403響應(yīng)
-
其它情況下拋出的異常弯洗,定向到error響應(yīng)
具體過程如圖:
ExceptionTranslationFilter攔截AuthenticationException新锈,并通過AuthenticationEntryPoint完成一下步處理谨敛。如果是基于form的認(rèn)證柿估,LoginUrlAuthenticationEntryPoint負(fù)責(zé)將用戶定向到登錄頁面跳夭。如果是其它認(rèn)證方式,需要實現(xiàn)該接口烈炭,確保未認(rèn)證時能重定向到指定的地址溶锭。
ExceptionTranslationFilter通過AccessDeniedHandler處理AccessDeniedException。如果配置了errorPage符隙,AccessDeniedHandler將異常轉(zhuǎn)發(fā)到errorPage,否則使用容器默認(rèn)的HTTP403頁面垫毙。在之前的幾節(jié)霹疫,我們處理未授權(quán)時,Spring Security默認(rèn)使用容器的HTTP403頁面综芥。
通過修改配置可以設(shè)置自定義AccessDenied處理界面
1 修改WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/assets/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/error").permitAll()
.antMatchers("/**").hasRole("USER")
.and().formLogin().loginPage("/login.jsp").permitAll().loginProcessingUrl("/login")
.and().logout().permitAll()
//配置未授權(quán)處理地址
.and().exceptionHandling().accessDeniedPage("/accessDenied")
.and().rememberMe().tokenRepository(persistentTokenRepository())
.and().csrf().disable();
}
2 創(chuàng)建Controll處理自定義/accessDenied請求
/**
* 登錄丽蝎、注銷、未授權(quán)異常處理
*
* Created by Administrator on 2017/8/1.
*/
@Controller
@RequestMapping("/")
public class LoginLogoutController {
@RequestMapping(value = "/accessDenied", method = RequestMethod.GET)
public ModelAndView accessDenied(HttpServletRequest request) {
ModelAndView modelAndView = new ModelAndView();
AccessDeniedException exception = (AccessDeniedException) request.getAttribute(WebAttributes.ACCESS_DENIED_403);
modelAndView.getModelMap().addAttribute("errorDetails", exception.getMessage());
StringWriter stringWriter = new StringWriter();
exception.printStackTrace(new PrintWriter(stringWriter));
modelAndView.getModelMap().addAttribute("errorTrace", stringWriter.toString());
modelAndView.setViewName("accessDenied");
return modelAndView;
}
}
3 AccessDeniedException界面/WEB-INF/views/accessDenied.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2017/8/1
Time: 14:02
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Access Denied</title>
</head>
<body>
<h1>Access Denied</h1>
<p>
Access to the specified resource has bean denied for the following reason:<strong>${errorDetails}</strong>
</p>
<em>Error Details(for Support Purpose only:)</em>
<br />
<blockquote>
<pre>${errorTrace}</pre>
</blockquote>
</body>
</html>
啟動服務(wù)器膀藐,用戶名為User登錄系統(tǒng)屠阻,點(diǎn)擊未授權(quán)服務(wù),系統(tǒng)將跳轉(zhuǎn)到自定義的報錯界面额各。
Spring Security事件
Spring Security基于Spring的事件發(fā)布機(jī)制處理認(rèn)證時發(fā)生的事件国觉。認(rèn)證事件實現(xiàn)了ApplicationEvent接口。通過獲取這些事件我們可以記錄認(rèn)證領(lǐng)域的行為虾啦。
事件是典型的訂閱-發(fā)布模式麻诀,通知訂閱者由Spring扶著痕寓。發(fā)布流程如下:
這里我們簡單實現(xiàn)一下認(rèn)證過程的事件跟蹤。
1 配置AuthenticationEventPublisher蝇闭。修改WebSecurityConfigurerAdapter
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationEventPublisher(authenticationEventPublisher())//注入事件發(fā)布者
.jdbcAuthentication()
.passwordEncoder(passwordEncoder())//啟用密碼加密功能
.dataSource(dataSource);
}
/**
* Description:認(rèn)證事件發(fā)布器
*
* @Author: 瓦力
* @Date: 2017/8/1 16:55
*/
@Bean
public AuthenticationEventPublisher authenticationEventPublisher() {
return new DefaultAuthenticationEventPublisher();
}
2 創(chuàng)建認(rèn)證事件處理器
/**
* 接收Spring Security發(fā)布的AbstractAuthenticationEvent
*
* Created by Administrator on 2017/8/1.
*/
@Component
public class AuthenticationEventListener implements ApplicationListener<AbstractAuthenticationEvent> {
@Override
public void onApplicationEvent(AbstractAuthenticationEvent event) {
System.out.println("Receive event of type:" + event.getClass().getName() + ":" + event.toString());
}
}
啟動服務(wù)呻率,登錄用戶,注銷用戶呻引,控制臺就會輸出認(rèn)證過程中發(fā)生的各種事件信息礼仗。
代碼示例:https://github.com/wexgundam/spring.security/tree/master/ch14