美文网首页
Spring Security 错误处理

Spring Security 错误处理

作者: Gavin黄炯鹏 | 来源:发表于2019-03-06 09:52 被阅读0次

    1.Spring Security 简单介绍

    spring security 是用来做安全验证的框架。默认状态下它有十个拦截器。使用者可以添加自定义拦截器并决定新增拦截器的顺序。一开始我以为像在controller层那样,遇到错误直接throw,但是这样做框架会跳到默认的错误页面,这不是我的需求。下面记录下错误处理的步骤.

    2.新建错误处理器

    新建自定义错误处理器,继承SimpleUrlAuthenticationFailureHandler类。框架默认使用的是这个类,onAuthenticationFailure是处理错误的方法,默认是跳到框架的验证入口(默认是登陆页面).这里做一些修改,假如是ajax请求,就返回json;假如不是,就跳到自定义页面.

    public class SessionAuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {
    
        private Logger logger = Logger.getLogger(getClass());
    
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
    
            logger.info("session过期");
            
            if(isAjaxRequest(request)){
                //返回json
                response.setStatus(500);
                response.setContentType("text/html;charset=utf-8");
                PrintWriter out = response.getWriter();
                out.print(StrUtils.getResponseJson(e.getMessage(),false));
                out.flush();
                out.close();
            }else{
                String url = "/showTip";
                //重定向到指定页面
                getRedirectStrategy().sendRedirect(request, response, url);
            }
        }
        
        private boolean isAjaxRequest(HttpServletRequest request) {
            String header = request.getHeader("X-Requested-With");
            if (header != null && "XMLHttpRequest".equals(header)){
                return true;
            }else{
                return false;
            }
     }
    }
    

    3.新建自定义过滤器

    新建过滤器,使用之前编写的错误处理器。在过滤器中捕捉SessionExpireException(继承AuthenticationException),然后执行之前重写的onAuthenticationFailure方法.

    我看框架的过滤器链,其中倒数第二个是ExceptionTranslationFilter,它是用作处理security异常的过滤器,我以为不管在哪个过滤器发生错误,都要向下继续执行过滤器,后来我发现是不对的,所以ExceptionTranslationFilter这个过滤器的意义是什么呢?

    public class SessionFilter extends OncePerRequestFilter {
        
        private AuthenticationFailureHandler failureHandler = new SessionAuthenticationFailHandler();
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            if (request.getRequestURI().contains("/login") || 
                    request.getRequestURI().contains("/resources") ||
                    request.getRequestURI().contains("/view") ||
                    request.getRequestURI().contains("/common") ||
                    request.getRequestURI().contains("/captcha") ||
                    request.getRequestURI().equals("/admin/admin/baseSet") ||
                    request.getRequestURI().equals("/showTip")) {
                filterChain.doFilter(request, response);
                return ;
            }
            
            try {
                isLogin(request);
            }
            catch (SessionExpireException e) {
                failureHandler.onAuthenticationFailure(request, response, e);
                return;//返回,不再向下执行.
            }
            filterChain.doFilter(request, response);
        }
    
        private void isLogin(HttpServletRequest request) throws AuthenticationException {
            if (request.getSession().getAttribute(Constants.SESSION_LOGIN_USER) == null) { 
                throw new SessionExpireException();
            }
        }
    
    }
    
    public class SessionExpireException extends AuthenticationException {
    
        public SessionExpireException() {
            super("用户Session已过期");
            // TODO Auto-generated constructor stub
        }
    
    }
    
    

    4.将自定义过滤器加入框架中

        @Configuration
        @EnableWebSecurity
        @EnableGlobalMethodSecurity(prePostEnabled=true)
        public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            
            ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
            
            // 把SessionFileter 放在 FilterSecurityInterceptor前面。
            http.addFilterBefore(new SessionFilter(), FilterSecurityInterceptor.class);
        }
    

    相关文章

      网友评论

          本文标题:Spring Security 错误处理

          本文链接:https://www.haomeiwen.com/subject/kegzuqtx.html