2017-07-26 83 views
0

我有一個簡單的帶有2個端點的Spring Boot REST API,其中一個是受保護的,一個不是。對於一個受保護的,我想趕上AccessDeniedException併發送401而不是默認的500錯誤。這裏是我的安全配置:如何在Spring Boot REST API中捕獲AccessDeniedException

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter{ 

@Override 
public void configure(WebSecurity webSecurity) { 
    webSecurity.ignoring().antMatchers("/"); 
} 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
      .exceptionHandling() 
      .accessDeniedHandler(new AccessDeniedHandler() { 
       @Override 
       public void handle(HttpServletRequest request, HttpServletResponse response, org.springframework.security.access.AccessDeniedException accessDeniedException) throws IOException, ServletException { 
        System.out.println("I am here now!!!"); 
       } 
      }); 

    http 
      .addFilterAfter(getSecurityFilter(), FilterSecurityInterceptor.class); 
    http 
      .sessionManagement() 
      .sessionCreationPolicy(SessionCreationPolicy.STATELESS); 
    http 
      .csrf() 
      .disable(); 
    http 
      .authorizeRequests() 
      .antMatchers("/protected").anonymous(); 
} 

public Filter getSecurityFilter() { 
    return new Filter() { 
     @Override 
     public void init(FilterConfig filterConfig) throws ServletException { 
      //do nothing here 
     } 

     @Override 
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
      String appKeyHeaderValue = ((HttpServletRequest)request).getHeader("X-AppKey"); 
      if(appKeyHeaderValue!=null && appKeyHeaderValue.equals("MY_KEY")) { 
       chain.doFilter(request,response); 
      } else { 
       throw new AccessDeniedException("Access denied man"); 
      } 
     } 

     @Override 
     public void destroy() { 

     } 
    }; 
} 

}

我從來沒有看到我的I am here now!!!打印語句,我反而看到的是默認的頁面 Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Tue Jul 25 23:21:15 CDT 2017 There was an unexpected error (type=Internal Server Error, status=500). Access denied man 注意如何我Access denied man並得到從異常時正在打印拋出。

當我運行該項目,我也看到在控制檯以下: 2017-07-25 23:21:14.818 INFO 3872 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2017-07-25 23:21:14.818 INFO 3872 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)

這裏是我的項目結構看起來像:

enter image description here

+0

可以設置的,而不是狀態代碼401「拋出新AccessDeniedException異常(‘拒絕訪問人’)」中的doFilter( .....) 方法? –

+0

我可以嘗試,但最終目標是有一個類來處理所有的異常,包括'AccessDeniedException' –

+0

所以你需要處理一個類中的所有異常嗎?右一confgiuration類,將延伸WebMvcConfigurerAdapter然後添加該重寫方法:@Override \t公共無效configureHandlerExceptionResolvers(列表 exceptionResolvers){ \t \t \t \t exceptionResolvers.add(新CustomHandlerExceptionResolver()); \t} –

回答

1

正如@Afridi建議發生異常在它到達控制器之前,所以它必須在過濾器鏈中處理。我建議做到以下幾點:

public class AccessDeniedExceptionFilter extends OncePerRequestFilter { 

    @Override 
    public void doFilterInternal(HttpServletRequest req, HttpServletResponse res, 
           FilterChain fc) throws ServletException, IOException { 
     try { 
      fc.doFilter(request, response); 
     } catch (AccessDeniedException e) { 
     // log error if needed here then redirect 
    RequestDispatcher requestDispatcher = 
      getServletContext().getRequestDispatcher(redirecturl); 
    requestDispatcher.forward(request, response); 

    } 
} 

添加此過濾器來過濾鏈

protected void configure(HttpSecurity http) throws Exception { 
http 
.... 
.addFilterAfter(httpClientFilter(), AccessDeniedExceptionFilter.class) 
+0

好的,我會查看文檔,看看是否有幫助,到目前爲止,我嘗試按照你的建議做,並刪除'.accessDeniedHandler',但這不起作用。我嘗試添加它並讓我的ControllerAdvice類實現'AccessDeniedHandler'並添加'.accessDeniedHandler'作爲參數傳遞了我的'ControllerAdvice',並且這些都不起作用 –

+0

您的端點有哪些註釋? – fg78nc

+0

我無法弄清楚如何在「迴應」這裏的格式,但他我有什麼 '@RestController 公共類ProtectedTestController { @RequestMapping(「/保護」) 公共ResponseEntity 家(){ return ResponseEntity.ok(「Hello protected」); } }' –

相關問題