2014-01-16 2 views
10

주석 기반 메서드 수준 보안을 사용할 때 Spring 3.2.4를 사용 중이며 스프링 보안을 access-denied-handler으로 리디렉션 할 수 없습니다. 이것에 대해 여러 가지 다른 게시물을 발견했지만, 현재까지 내가 찾은 해결책이없는 것 같습니다.스프링 보안 메서드 수준 보안을 사용하는 액세스 거부 처리기를 무시합니다.

내 security.xml 파일 :

<!-- need this here to be able to secure methods in components other than controllers (as scanned in applicationContext.xml) --> 
<global-method-security secured-annotations="enabled" pre-post-annotations="enabled" jsr250-annotations="enabled" ></global-method-security> 

<!-- Annotation/JavaConfig examples http://stackoverflow.com/questions/7361513/spring-security-login-page --> 
<http use-expressions="true" entry-point-ref="authenticationEntryPoint"> 
    <access-denied-handler ref="accessDeniedHandler"/> 

    <intercept-url pattern="/secure/login" access="permitAll" /> 
    <intercept-url pattern="/secure/logout" access="permitAll" /> 
    <intercept-url pattern="/secure/denied" access="permitAll" /> 
    <session-management session-fixation-protection="migrateSession" session-authentication-error-url="/login.jsp?authFailed=true"> 
     <concurrency-control max-sessions="10" error-if-maximum-exceeded="true" expired-url="/login.html" session-registry-alias="sessionRegistry"/> 
    </session-management> 

    <intercept-url pattern="/**" access="isAuthenticated()" /> 
    <form-login default-target-url="/" authentication-failure-url="/secure/denied" /> 
    <logout logout-url="/secure/logout" logout-success-url="/" /> 
    <expression-handler ref="defaultWebSecurityExpressionHandler" /> 
</http> 

<beans:bean id="authenticationEntryPoint" class="com.ia.security.LoginUrlAuthenticationEntryPoint"> 
    <beans:constructor-arg name="loginFormUrl" value="/secure/login"/> 
</beans:bean> 

<beans:bean id="accessDeniedHandler" class="com.ia.security.AccessDeniedHandlerImpl"> 
    <beans:property name="errorPage" value="/secure/denied"/> 
</beans:bean> 

내 AccessDeniedHandlerImpl.java :

public class AccessDeniedHandlerImpl extends org.springframework.security.web.access.AccessDeniedHandlerImpl { 
    // SLF4J logger 
    private static final Logger logger = LoggerFactory.getLogger(AccessDeniedHandlerImpl.class); 

    @Override 
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 
     logger.log("AccessDeniedException triggered!"); 
     super.handle(request, response, accessDeniedException); 

    } 
} 

내 주석 방법 : 나는하도록 할 필요가 특별한 아무것도

@PreAuthorize("hasAuthority('ROLE_ZZZZ')") 
public ModelAndView getUserInfo(@PathVariable long userId){ 
    ModelAndView mv = new ModelAndView(); 
    User u = userService.findUser(userId); 
    mv.addObject("user", u); 
    return mv; 
} 

있는가 내 액세스 거부 처리기가 호출됩니까?

답변

15

몇 시간 동안 스프링 코드를 검색하고 추적 한 결과, 마침내 무슨 일이 일어나는지 발견했습니다. 나는 그것이 다른 사람에게 가치가있는 경우를 대비하여 여기에 목록으로 남겼습니다.

access-denied-handlerAccessDeniedException의 경우 ExceptionTranslationFilter에 사용됩니다. 그러나 org.springframework.web.servlet.DispatcherServlet은 먼저 예외 처리를 시도했습니다. 특히 org.springframework.web.servlet.handler.SimpleMappingExceptionResolverdefaultErrorView으로 정의되었습니다. 결과적으로 SimpleMappingExceptionResolver은 적절한보기로 리디렉션하여 예외를 사용하고 있었기 때문에 ExceptionTranslationFilter까지 버블 링 될 예외는 없었습니다.

수정 사항은 간단합니다. SimpleMappingExceptionResolver이 모두 AccessDeniedException을 무시하도록 구성하십시오. AccessDeniedException가 발생 될 때마다

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 
    <property name="defaultErrorView" value="uncaughtException" /> 
    <property name="excludedExceptions" value="org.springframework.security.access.AccessDeniedException" /> 

    <property name="exceptionMappings"> 
     <props> 
      <prop key=".DataAccessException">dataAccessFailure</prop> 
      <prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</prop> 
      <prop key=".TypeMismatchException">resourceNotFound</prop> 
      <prop key=".MissingServletRequestParameterException">resourceNotFound</prop> 
     </props> 
    </property> 
</bean> 

지금, 리졸버는 그것을 무시하고 거품까지 다음 예외를 처리 할 수 ​​ access-denied-handler에 호출 ExceptionTranslationFilter에 스택에 있습니다.

+0

아직받지 못했습니다. 또한 정확하게 설명했지만 문제가 발생하지 않았습니다. ( – Cataclysm

+4

javaconfig? – Vivek

+0

@Eric이 솔루션에 대한 Java Config를 공유 할 수 있습니까? –

5

동일한 문제가 발생합니다. 내 경우에서 @ControllerAdvise가 예외를 처리해야하는 definied 이미 있었다 - 그래서 나는 직접 AccessDeniedException을 추가 :

@Component 
@ControllerAdvice 
public class ControllerBase { 

... 

    @ExceptionHandler(value = AccessDeniedException.class) 
    public ModelAndView accessDenied() { 
     return new ModelAndView("redirect:login.html"); 
    } 
} 

행운을 함께!

0

SimpleMappingExceptionResolver에 대한 JavaConfig를 사용하여 에릭 답변을 확장하면 AccessDeniedException이 무시되어 응답으로 throw 될 수 있고 SimpleMappingExceptionResolver에 의해 삼켜지지 않습니다.

@Configuration 
@EnableWebMvc 
public class AppConfig extends WebMvcConfigurerAdapter { 

    @Bean 
    public SimpleMappingExceptionResolver exceptionResolver() { 
    SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); 
    exceptionResolver.setExcludedExceptions(AccessDeniedException.class); 
    return exceptionResolver; 
    } 

} 
관련 문제