ch14:異常處理與認(rèn)證事件處理

Spring Security異常處理

Spring Security在Filter chain中使用ExceptionTranslationFilter檢查并處理在認(rèn)證和授權(quán)過(guò)程中拋出的異常。該Filter支持處理或者分發(fā)三種常規(guī)異常行為:

  1. 未認(rèn)證拋出的AuthenticationException,定向到用戶登錄界面
  2. 未授權(quán)拋出的AccessDeniedException,定向到403響應(yīng)
  3. 其它情況下拋出的異常,定向到error響應(yīng)
    具體過(guò)程如圖:


    Paste_Image.png

ExceptionTranslationFilter攔截AuthenticationException,并通過(guò)AuthenticationEntryPoint完成一下步處理。如果是基于form的認(rèn)證,LoginUrlAuthenticationEntryPoint負(fù)責(zé)將用戶定向到登錄頁(yè)面。如果是其它認(rèn)證方式,需要實(shí)現(xiàn)該接口,確保未認(rèn)證時(shí)能重定向到指定的地址。

ExceptionTranslationFilter通過(guò)AccessDeniedHandler處理AccessDeniedException。如果配置了errorPage,AccessDeniedHandler將異常轉(zhuǎn)發(fā)到errorPage,否則使用容器默認(rèn)的HTTP403頁(yè)面。在之前的幾節(jié),我們處理未授權(quán)時(shí),Spring Security默認(rèn)使用容器的HTTP403頁(yè)面。

通過(guò)修改配置可以設(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請(qǐng)求

/**
 * 登錄、注銷、未授權(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>

啟動(dòng)服務(wù)器,用戶名為User登錄系統(tǒng),點(diǎn)擊未授權(quán)服務(wù),系統(tǒng)將跳轉(zhuǎn)到自定義的報(bào)錯(cuò)界面。

Spring Security事件

Spring Security基于Spring的事件發(fā)布機(jī)制處理認(rèn)證時(shí)發(fā)生的事件。認(rèn)證事件實(shí)現(xiàn)了ApplicationEvent接口。通過(guò)獲取這些事件我們可以記錄認(rèn)證領(lǐng)域的行為。
事件是典型的訂閱-發(fā)布模式,通知訂閱者由Spring扶著。發(fā)布流程如下:


Paste_Image.png

這里我們簡(jiǎn)單實(shí)現(xiàn)一下認(rèn)證過(guò)程的事件跟蹤。
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());
    }
}

啟動(dòng)服務(wù),登錄用戶,注銷用戶,控制臺(tái)就會(huì)輸出認(rèn)證過(guò)程中發(fā)生的各種事件信息。

代碼示例:https://github.com/wexgundam/spring.security/tree/master/ch14

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容