inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

코드로 배우는 React 19 with 스프링부트 API서버

JWT와 @PreAuthorize 이용하기

AccessDeniedHandler가 작동하지않습니다

181

고래돌

작성한 질문수 3

0

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

    try {

        생략...
 
        SecurityContextHolder.getContextHolderStrategy().getContext().setAuthentication(token);

        filterChain.doFilter(request, response);

    } catch (Exception e) {

        log.info("---------------JWT ERROR!------------");
        log.info(e);
        log.info(e.getMessage());

        ObjectMapper mapper = new ObjectMapper();
        String jsonStr = mapper.writeValueAsString(Map.of("error", "ERROR_ACCESS_TOKEN"));

        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        PrintWriter writer = response.getWriter();
        writer.println(jsonStr);
        writer.close();

    }

}

강의의 JWT와 @PreAuthorize 이용하기 파트 후반부에 강의처럼 USER권한만 가진 사용자로 ADMIN권한이 필요한 메소드에 접근하니 포스트맨에서 AccessDenied exception이 뜨지않고
catch (Exception e)가 예외를 잡아버려서

 

{
    "error": "ERROR_ACCESS_TOKEN"
}

결과가 이렇게 나옵니다 이미 AccessDenied 핸들러도 시큐리티에 등록 시킨후 입니다
ADMIN권한을 가진 사용자 토큰으로 요청을 보내면 원하는 데이터도 잘 나옵니다


catch로 잡아서 예외를 던질까 시도해봤는데 이유는 모르겠지만 Exception에서만 예외가 잡힙니다ㅠ

그래서 여러가지 해결책을 알아봤는데
첫번째

catch (RuntimeException e) {

    log.info("---------------JWT ERROR!------------");
    log.info(e);
    log.info(e.getMessage());

    ObjectMapper mapper = new ObjectMapper();
    String jsonStr = mapper.writeValueAsString(Map.of("error", "ERROR_ACCESS_TOKEN"));

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");

    PrintWriter writer = response.getWriter();
    writer.println(jsonStr);
    writer.close();

}

이렇게 RuntimeException으로하면

{
    "error": "ERROR_ACCESSDENIED"
}

AccessDenied 핸들러가 잘 작동하구요

두번째

SecurityContextHolder.getContextHolderStrategy().getContext().setAuthentication(token);
    
} catch (Exception e) {

    log.info("---------------JWT ERROR!------------");
    log.info(e);
    log.info(e.getMessage());

    ObjectMapper mapper = new ObjectMapper();
    String jsonStr = mapper.writeValueAsString(Map.of("error", "ERROR_ACCESS_TOKEN"));

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");

    PrintWriter writer = response.getWriter();
    writer.println(jsonStr);
    writer.close();

}

filterChain.doFilter(request, response);

doFilter를 try catch 밖에 두어도 AccessDenied 핸들러가 잘 작동합니다

세번째

@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<?> notAuthorized(AccessDeniedException e) {

    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
}

RestControllerAdvice로 하면 핸들러가 작동안하긴해도 예외처리가 가능했습니다

근데 문제는 왜 원래코드에서 영상처럼 작동을 안하는지 이유를 모르겠습니다 제가 빠트린부분이 있을까요?
스프링부트 버전도 똑같이 맞춰보기도 했습니다

react spring-boot jpa jwt redux-toolkit

답변 1

0

구멍가게코딩단

질문을 보고 다시 한번 소스 코드를 실행해서 결과를 확인했습니다만 문제가 발생하지 않았습니다.

 

예제 코드는 해당 섹션의 마지막쪽에 수업자료로 등록되어 있으니 다운로드 받아서 실행해 보실 수 있습니다.

 

Access Denied는 시큐리티에 관리되는 UserDetails를 통해서 처리되므로

UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(memberDTO, pw, memberDTO.getAuthorities());

SecurityContextHolder.getContext().setAuthentication(authenticationToken);

authenticationToken의 값이 어떻게 나오는지 확인이 필요합니다.

 

 

말씀하신 문제는 작성하신 코드를 보면서 실행해 봐야 원인을 알 수 있을 듯 합니다.

 

코드를 https://drive.google.com/drive/folders/1ZLHRKaXx8Ou8kZNd1WE6qALxq_wJODXW?usp=drive_link

에 올려주시거나 코드를 접근할 수 있는 방법을 cookie_00@naver.com으로 알려주시면 살펴볼 수 있을듯 합니다.

 

0

고래돌

답변감사합니다 프로젝트 파일 db username 과 password만 지우고 드라이브에 올렸습니다 UserDetails 구현은 CustomUserDetails에서 했습니다

0

구멍가게코딩단

JWTCheckFilter에서 예외를 잡아서 직접 던지시는게 제일 간단합니다. 강의와 다른 버전이라.. 좀 더 테스트가 필요하긴 하지만 우선 해결책으로.. 예외를 잡아서 던지시면 처리가 되실 겁니다.

 

 

 

    SecurityContextHolder.getContextHolderStrategy().getContext().setAuthentication(token);

    filterChain.doFilter(request, response);
}catch(ServletException e){

    throw e;

} catch (Exception e) {

    log.info("---------------JWT ERROR!------------");
    log.info(e);
    log.info(e.getMessage());

 

0

고래돌

강의에서 사용한 스프링부트 버전이 3.1.5 버전이라 3.1.5로 다운그레이드도 해봤는데 동일한 결과가 타나나더라구요ㅠ
jjwt 버전이 좀더 최신이여서 문제가 되지는 않을거같은데...
해결책으로 주신방법은 AccessDenied 핸들러가 잘 작동합니다

근데 로그창에

image.png

이런 로그도 같이뜨네요..

0

구멍가게코딩단

강의 코드 역시 버전 업을 시키니 예외 발생 메시직가 동일하게 나옵니다.

다만 버전업을 시켜도 별도의 추가적인 예외 처리를 하지는 않았습니다.

 

개인적으로 작성하신 코드의 내부를 좀 더 살펴봐야 원인을 알 수 있을 듯 합니다.

0

고래돌

넵 감사합니다 저도 열심히 찾아보는데 답이 안보이네요

동일하게 실습하는데 이상하게 페이지를 찾지 못하네요..

0

74

2

22. REST 방식 컨트롤러 만들기(2), 29. 등록처리 부분 질문이 있습니다.

0

74

2

37강. 강의수업듣다 질문드립니다.

0

57

2

TodoDTO test 함수

0

80

3

강사님 오타 있음요

0

78

2

No 1. 교제(ppt) soruce 복붙 문제 의 건

0

95

4

No 1. 교제(ppt) soruce 복붙 문제 의 건

0

70

3

17강 문의드립니다.

0

44

1

카카오 연동설정이 이제 안되는거 같아요

0

191

2

8장 마지막 강의 시 오류

0

98

4

혹시 뭐가 문제인지 알 수 있나요?

0

87

2

챕터: React-Router 설정

0

58

2

백)TODO관련

0

56

2

마리아 db 설치중 포트를 이미 사용중이라고 합니다

0

112

2

이강의 듣고 소화시켰다면 몇년차 정도 개발자라고 할수 있을까요?

0

105

1

CSR , SSR 의 수요 궁금증 질문

0

83

2

섹션5부터...

0

73

1

간단한 코드 질문!!

0

61

2

tbl_todo 질문입니다

0

65

2

수업 외 질문인데 'tbl'이 무슨 의미인가요???

0

292

2

엔티티클래스에서 질문입니다

0

78

2

수정시 writer값이 삭제되는 오류

0

42

2

교안 31 오타 수정해주세요

0

64

2

쿠키에 accessToken, refreshToken을 담고, 조회 시에 undefined

0

80

1