복붙노트

[SPRING] 스프링 보안 로그 아웃이 작동하지 않음 - 보안 컨텍스트를 지우지 않고 인증 된 사용자가 여전히 존재 함

SPRING

스프링 보안 로그 아웃이 작동하지 않음 - 보안 컨텍스트를 지우지 않고 인증 된 사용자가 여전히 존재 함

나도 알아,이 주제에 대한 많은 기사가 있지만 문제가있어 해결책을 찾을 수 없습니다.

나는 고전적인 봄 보안 자바 설정을 가지고있다 :

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private AuctionAuthenticationProvider auctionAuthenticationProvider;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(auctionAuthenticationProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic();

    ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequest = http.authorizeRequests();

    configureAdminPanelAccess(authorizeRequest);
    configureFrontApplicationAccess(authorizeRequest);
    configureCommonAccess(authorizeRequest);

    http.csrf()
        .csrfTokenRepository(csrfTokenRepository()).and()
        .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);

    http.logout()
        .clearAuthentication(true)
        .invalidateHttpSession(true);
}
...
}

또한 AJAX가 내 웹 응용 프로그램에서 로그인 / 로그 아웃하는 두 가지 컨트롤러 메서드가 있습니다.

로그 아웃하고 싶을 때 먼저이 메서드를 호출합니다.이 메서드는 사용자 세션을 지우고 보안 컨텍스트의 모든 항목을 지우려고합니다.

@Override
@RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<Boolean> logout(final HttpServletRequest request, final HttpServletResponse response) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null){
        new SecurityContextLogoutHandler().logout(request, response, auth);
    }

    return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK);
}

이 후 클라이언트 웹 응용 프로그램을 다시로드하고 다시로드 할 때마다 다음 컨트롤러 메서드를 호출하여 사용자가 인증되었는지 확인합니다.

@Override
@RequestMapping(value = "/user", method = GET, produces = APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<UserDetails> user() {
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    if (principal instanceof UserDetails) {
        return new ResponseEntity<>((UserDetails) principal, HttpStatus.OK);
    }

    return null;
}

여기에는 항상 마지막으로 인증 된 사용자가 표시됩니다. 이전 로그 아웃 방법에서는 스프링 로그 아웃이 작동하지 않는 것 같습니다.

성공하지 못한 채로 다음 코드를 사용하여 로그 아웃하려고 시도했음을 기억하십시오.

   @Override
   @RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Boolean> logout(final HttpServletRequest request) {
     try {
         request.logout();

         return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK);
     } catch (ServletException ex) {
         if (LOG.isDebugEnabled()) {
             LOG.debug("There is a problem with the logout of the user", ex);
         }
    }

내 구성 및 로그 아웃 프로세스에서 내가 놓친 것을 알고 있습니까?

해결법

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

    1.귀하의 질문에서, 나는 당신이 자신의 로그 아웃을 만들려고하고 또한 기본 스프링 로그 아웃을 사용하려고 시도하고 있음을 압니다. 한 가지 방법 만 선택하면됩니다. 두 가지 방법이 있습니다. 봄에서 로그 아웃 할 수있는 방법은 두 가지가 있습니다. :

    귀하의 질문에서, 나는 당신이 자신의 로그 아웃을 만들려고하고 또한 기본 스프링 로그 아웃을 사용하려고 시도하고 있음을 압니다. 한 가지 방법 만 선택하면됩니다. 두 가지 방법이 있습니다. 봄에서 로그 아웃 할 수있는 방법은 두 가지가 있습니다. :

    첫째 : 기본 스프링 보안 로그 아웃

    .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
    .logoutSuccessUrl("/logout.done").deleteCookies("JSESSIONID")
    .invalidateHttpSession(true) 
    

    위의 예에서 사용자를 로그 아웃 할 때마다 / logout url 만 호출하면됩니다. 그 대신 Spring을 사용하여 로그 아웃하는 @Controller를 생성 할 필요가 없습니다. 여기에서 무효화하려는 다른 것을 추가 할 수도 있습니다.

    둘째 : 프로그래밍 방식으로 로그 아웃

    @RequestMapping(value = {"/logout"}, method = RequestMethod.POST)
    public String logoutDo(HttpServletRequest request,HttpServletResponse response){
    HttpSession session= request.getSession(false);
        SecurityContextHolder.clearContext();
             session= request.getSession(false);
            if(session != null) {
                session.invalidate();
            }
            for(Cookie cookie : request.getCookies()) {
                cookie.setMaxAge(0);
            }
    
        return "logout";
    }
    

    이 로그 아웃을 사용하고 있다면 스프링 보안 설정에 첫 번째 방법을 포함 할 필요가 없습니다. 이 방법을 사용하면 로그 아웃 완료 전후에 수행 할 작업을 추가 할 수 있습니다.이 로그 아웃을 사용하려면 / logout url을 호출하면 사용자가 수동으로 로그 아웃됩니다.이 방법은 세션을 무효화하고 스프링 보안 컨텍스트와 쿠키를 삭제합니다 .

    두 번째 방법 이외에도 RequestMethod.POST를 사용하는 경우 csrf 키를 게시물로 포함시켜야합니다. 다른 방법은 숨겨진 입력 csrf 키가있는 양식을 만드는 것입니다. 다음은 jquery로 자동 생성 된 로그 아웃 링크의 예입니다.

    $("#Logout").click(function(){
        $form=$("<form>").attr({"action":"${pageContext.request.contextPath}"+"/logout","method":"post"})
        .append($("<input>").attr({"type":"hidden","name":"${_csrf.parameterName}","value":"${_csrf.token}"}))
        $("#Logout").append($form);
        $form.submit();
    });
    

    그것을 사용하려면 로그 아웃 하이퍼 링크를 만들어야합니다.

    RequestMethod.GET을 사용하는 경우 다음과 같이 링크 할 때 csrf 키를 매개 변수로 포함하십시오.

    <a href="${pageContext.request.contextPath}/logout?${_csrf.parameterName}=${_csrf.token}">Logout</a>
    

    그게 다 도움이 되길 바랍니다.

  2. ==============================

    2.이것은 도움이 될 것입니다, 나는 clearAuthentication (true)로 충분하다고 생각합니다 :

    이것은 도움이 될 것입니다, 나는 clearAuthentication (true)로 충분하다고 생각합니다 :

    @Configuration 
    @EnableWebSecurity 
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    ....
    
        @Override
        protected void configure(HttpSecurity http) throws Exception
        {
            http
            .httpBasic()
            .and()
            .logout().clearAuthentication(true)
            .logoutSuccessUrl("/")
            .deleteCookies("JSESSIONID")
            .invalidateHttpSession(true)
            .and()
    
  3. ==============================

    3.바로 위로 가기, Clear Site Data HTTP 헤더가 있습니다.

    바로 위로 가기, Clear Site Data HTTP 헤더가 있습니다.

    Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
    

    또한 Clear-Site-Data 헤더에 대한 지원을 Spring-Security 5.2 프로젝트에 추가하는 것을 도왔습니다. 구현에 대한 자세한 내용은 홍보를 참조하십시오.

    어떻게 작동하는지 예제가 있습니다.

    @EnableWebSecurity
    static class HttpLogoutConfig extends WebSecurityConfigurerAdapter {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .logout()
                        .addLogoutHandler(new HeaderWriterLogoutHandler(
                               new ClearSiteDataHeaderWriter(SOURCE)));
        }
    }
    

    SOURCE는 다음 중 하나 이상의 가변 값입니다.

    자세한 내용은 LogoutConfigurerClearSiteDataTests.java의 샘플 테스트를 참조하십시오.

  4. from https://stackoverflow.com/questions/36557294/spring-security-logout-does-not-work-does-not-clear-security-context-and-authe by cc-by-sa and MIT license