복붙노트

[SPRING] Spring Security와의 CSRF 통합시 Session timeout으로 인해 Spring MVC에서 Access Denied가 발생합니다.

SPRING

Spring Security와의 CSRF 통합시 Session timeout으로 인해 Spring MVC에서 Access Denied가 발생합니다.

Spring MVC 프로젝트에서 Spring Security와 통합 된 CSRF 토큰을 가지고있다. 모든 것이 CSRF 토큰으로 제대로 작동하며 토큰은 클라이언트 측에서 서버 측으로 전송됩니다.

CSRF 토큰을 보내고 POST 메서드를 제대로 작동하도록 로그 아웃 프로세스를 변경했습니다.

세션 시간 제한이 발생할 때 얼굴 문제가 있습니다. 스프링 기본 로그 아웃 URL로 리디렉션되어야하지만 해당 URL에서 액세스 거부가 발생합니다.

이 동작을 재정의하는 방법.

나는 보안 설정 파일에 아래 라인을 포함시켰다.

   <http>
         //Other config parameters
        <csrf/>
   </http>

누구든지 더 많은 정보가 필요하면 알려주십시오.

해결법

  1. ==============================

    1.질문은 조금 오래되었지만 대답은 항상 유용합니다.

    질문은 조금 오래되었지만 대답은 항상 유용합니다.

    첫째, 이것은 CSRF Caveats - Timeouts 문서에 설명 된대로 세션 지원 CSRF 토큰에 대한 알려진 문제입니다.

    이를 해결하기 위해 몇 가지 자바 스크립트를 사용하여 임박한 시간 초과를 감지하거나 세션 독립적 인 CSRF 토큰 리포지토리를 사용하거나 사용자 정의 AccessDeniedHandler 라우트를 만듭니다. 나는 후자를 선택했다 :

    구성 XML :

    <http>
        <!-- ... -->
        <access-denied-handler ref="myAccessDeniedHandler"/>
    </http>
    
    <bean id="myAccessDeniedHandler" class="package.MyAccessDeniedHandler">
        <!-- <constructor-arg ref="myInvalidSessionStrategy" /> -->
    </bean>
    

    AccessDeniedHandler :

    public class MyAccessDeniedHandler implements AccessDeniedHandler {
        /* ... */
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception)
                throws IOException, ServletException {
            if (exception instanceof MissingCsrfTokenException) {
                /* Handle as a session timeout (redirect, etc).
                Even better if you inject the InvalidSessionStrategy
                used by your SessionManagementFilter, like this:
                invalidSessionStrategy.onInvalidSessionDetected(request, response);
                */
            } else {
                /* Redirect to a error page, send HTTP 403, etc. */
            }
        }
    }
    

    또는 사용자 지정 처리기를 DelegatingAccessDeniedHandler로 정의 할 수 있습니다.

    <bean id="myAccessDeniedHandler" class="org.springframework.security.web.access.DelegatingAccessDeniedHandler">
        <constructor-arg name="handlers">
            <map>
                <entry key="org.springframework.security.web.csrf.MissingCsrfTokenException">
                    <bean class="org.springframework.security.web.session.InvalidSessionAccessDeniedHandler">
                        <constructor-arg name="invalidSessionStrategy" ref="myInvalidSessionStrategy" />
                    </bean>
                </entry>
            </map>
        </constructor-arg>
        <constructor-arg name="defaultHandler">
            <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
                <property name="errorPage" value="/my_error_page"/>
            </bean>
        </constructor-arg>
    </bean>
    
  2. ==============================

    2.mdrg가 제공 한 답은 바로 다음과 같습니다. 또한 사용자가 고려할 수 있도록 사용자 정의 AccessDeniedHandler를 구현했습니다.

    mdrg가 제공 한 답은 바로 다음과 같습니다. 또한 사용자가 고려할 수 있도록 사용자 정의 AccessDeniedHandler를 구현했습니다.

    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.security.web.access.AccessDeniedHandlerImpl;
    import org.springframework.security.web.csrf.MissingCsrfTokenException;
    import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
    import org.springframework.security.web.savedrequest.RequestCache;
    
    /**
     * Intended to fix the CSRF Timeout Caveat 
     * (https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf-timeouts).
     * When the session expires and a request requiring CSRF is received (POST), the
     * missing token exception is handled by caching the current request and 
     * redirecting the user to the login page after which their original request will
     * complete. The intended result is that no loss of data due to the timeout will
     * occur.
     */
    public class MissingCsrfTokenAccessDeniedHandler extends AccessDeniedHandlerImpl {
      private RequestCache requestCache = new HttpSessionRequestCache();
      private String loginPage = "/login";
    
      @Override
      public void handle(HttpServletRequest req, HttpServletResponse res, AccessDeniedException exception) throws IOException, ServletException {
        if (exception instanceof MissingCsrfTokenException && isSessionInvalid(req)) {
          requestCache.saveRequest(req, res);
          res.sendRedirect(req.getContextPath() + loginPage);
        }
        super.handle(req, res, exception);
      }
    
      private boolean isSessionInvalid(HttpServletRequest req) {
        try {
          HttpSession session = req.getSession(false);
          return session == null || !req.isRequestedSessionIdValid();
        }
        catch (IllegalStateException ex) {
          return true;
        }
      }
    
      public void setRequestCache(RequestCache requestCache) {
        this.requestCache = requestCache;
      }
    
      public void setLoginPage(String loginPage) {
        this.loginPage = loginPage;
      }
    } 
    

    자바 설정을 통해 유선 :

    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
      @Override
      protected void configure(HttpSecurity http) throws Exception {
        ...
        http.exceptionHandling().accessDeniedHandler(getAccessDeniedHandler());
        ...
      }
    
       public AccessDeniedHandler getAccessDeniedHandler() {
        return new MissingCsrfTokenAccessDeniedHandler();
      }
    }
    
  3. from https://stackoverflow.com/questions/27654206/session-timeout-leads-to-access-denied-in-spring-mvc-when-csrf-integration-with by cc-by-sa and MIT license