zoukankan      html  css  js  c++  java
  • 03. Spring Security 异常处理

    03. Spring Security 异常处理

    参考:

    https://blog.csdn.net/yuanlaijike/article/details/80250389

    不知道你有没有注意到,当我们登陆失败时候,Spring security 帮我们跳转到了 /login?error Url,奇怪的是不管是控制台还是网页上都没有打印错误信息。

    这是因为首先 /login?error 是 Spring security 默认的失败 Url,其次如果你不手动处理这个异常,这个异常是不会被处理的

    #常见异常

    我们先来列举下一些 Spring Security 中常见的异常:

    • UsernameNotFoundException(用户不存在)

    • DisabledException(用户已被禁用)

    • BadCredentialsException(坏的凭据)

    • LockedException(账户锁定)

    • AccountExpiredException (账户过期)

    • CredentialsExpiredException(证书过期)

    以上列出的这些异常都是 AuthenticationException 的子类,然后我们来看看 Spring security 如何处理 AuthenticationException 异常的。

    #源码分析

    AbstractAuthenticationProcessingFilterdoFilter()上打一个断点

    发现try-catch捕捉了attemptAuthentication(request, response);抛出的异常

    并执行了unsuccessfulAuthentication(request, response, failed);

    然后将异常交给SimPleUrlAuthenticationFailureHandeler

    转到方法能明显的看到发送了/login?error请求

    如果没有是指defaultFailureUrl直接返回UNAUTHORIZED(401)

    然后执行saveException(request, exception)

    然后判断 forwardToDestination ,即是否是服务器跳转,默认使用重定向即客户端跳转。

    这里可以发现设置了key为SPRING_SECURITY_LAST_EXCEPTION, value为AuthenticationException

    到session域中, 所以我们也就可以通过SPRING_SECURITY_LAST_EXCEPTION获取到对应的exception的值

    #处理异常

    方法一

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/login").permitAll()
                    .anyRequest()
                    .authenticated()
                    .and()
                    .formLogin()
                    .loginPage("/login")
                    .successForwardUrl("/")
                    //登入失败跳转url,重定向
                    .failureUrl("/fail")
                    .and()
                    .logout().permitAll()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/login")
                    .clearAuthentication(true)
                    .invalidateHttpSession(true)
                    .deleteCookies("JSESSIONID")
                    .and()
                    .rememberMe()
                    .tokenValiditySeconds(60)
                    .tokenRepository(persistentTokenRepository())
                    .userDetailsService(userDetailsService)
                    .and()
                    .csrf()
                    .disable();
        }
    
        @ResponseBody
    	@GetMapping("/fail")
        public Object fail(HttpServletRequest req, HttpServletResponse resp){
            log.info("failure into this ");
            //设置编码防止乱码
            resp.setContentType("application/json;charset=utf-8");
            AuthenticationException exception = (AuthenticationException)
                    req.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
            return exception;
        }
    

    方法二(推荐)

    修改配置类

    .successForwardUrl("/")

    POST方式请求转发

        @ResponseBody
        @ResponseStatus(HttpStatus.UNAUTHORIZED)
        @PostMapping("/fail")
        public String fail() {
            return "账号或密码错误";
        }
    

    方法三

    修改配置类

    .failureHandler(failureHandler())

    使用自定的handler, 需要将该类注入到ioc中

    • 返回Json
    public class FailureHandler implements AuthenticationFailureHandler {
        @Autowired
        ObjectMapper mapper;
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().print(mapper.writeValueAsString(exception));
        }
    }
    
    • 重定向
    public class FailureHandler implements AuthenticationFailureHandler {
        private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
        @Autowired
        ObjectMapper mapper;
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
            response.setContentType("application/json;charset=utf-8");
            redirectStrategy.sendRedirect(request,response,"/fail");
        }
    }
    
  • 相关阅读:
    SQL 取日期
    myeclipse 8.5 安装jbpm3.2开发插件
    持续感悟
    程序员应该读的书与经常上的网站
    java连接ms sql server各类问题解析
    怎么实现Redis的高可用?(主从、哨兵、集群)
    Web系统突然爆”Asp.net ajax客户端框架未能加载“的一种可能原因(误改服务器系统时间)
    【转】Skyline软件介绍
    ArcSDE启动遇到ORA12560: TNS: 协议适配器错误解决办法
    开放源代码GIS资源集锦
  • 原文地址:https://www.cnblogs.com/kikochz/p/12892452.html
Copyright © 2011-2022 走看看