JWT와 @PreAuthorize 사용하기에서 권한오류
158
작성한 질문수 3
동영상 강의에 있는 내용대로 ProductController에서 @GetMapping("/list")에 @PreAuthorize("hasAnyRole('ROLE_USER','ROLE_ADMIN')")를 작성하고나서 postman에 login 후 accessToken을 가져와서 get방식으로 토큰을 넣어서 입력하면 status : 500, "error": Interner Server Error가 뜹니다.. @PreAuthorize부분을 주석처리하고 실행해보면 list값이 잘 나오네요.. 어디부분이 잘못 된걸까요??
참고로 CustomSecurityConfig클래스에 @EnableMethodSecurity추가도 했습니다.
@PreAuthorize("hasAnyRole('ROLE_USER','ROLE_ADMIN')")
@GetMapping("/list")
public PageResponseDTO<ProductDTO> list(PageRequestDTO pageRequestDTO){
return productService.getList(pageRequestDTO);
}
여기가 ProductController 클래스
package org.zerock.apiserver.security.filter;
import com.google.gson.Gson;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import org.zerock.apiserver.dto.MemberDTO;
import org.zerock.apiserver.util.JWTUtil;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
@Log4j2
public class JWTCheckFilter extends OncePerRequestFilter {
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
//true == not check
String path = request.getRequestURI();
log.info("------check uri---------"+path);
if(path.startsWith("/api/member/")){
return true;
}
//false == check
return false;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
log.info("----------------------");
log.info("----------------------");
log.info("----------------------");
String autoHeaderStr = request.getHeader("Authorization");
//bearer // 7개 후 JWT 문자열
try {
String accessToken = autoHeaderStr.substring(7);
Map<String, Object> claims = JWTUtil.validateToken(accessToken);
log.info("JWT claims: " + claims);
// filterChain.doFilter(request, response);
String email = (String) claims.get("email");
String pw = (String) claims.get("pw");
String nickname = (String) claims.get("nickname");
Boolean social = (Boolean) claims.get("social");
List<String> roleNames = (List<String>) claims.get("roleNames");
MemberDTO memberDTO = new MemberDTO(email, pw, nickname, social.booleanValue(), roleNames);
log.info("---------------------------------");
log.info(memberDTO);
log.info(memberDTO.getAuthorities());
UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(memberDTO, pw, memberDTO.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
filterChain.doFilter(request, response);
}catch(Exception e){
log.error("JWT Check Error --------------------");
log.error(e.getMessage());
Gson gson = new Gson();
String msg = gson.toJson(Map.of("error", "ERROR_ACCESS_TOKEN"));
response.setContentType("application/json");
PrintWriter printWriter = response.getWriter();
printWriter.println(msg);
printWriter.close();
}
//destination
filterChain.doFilter(request, response);
}
}
여기가 JWTCheckFilter부분입니다.
답변 2
1
음.. 500 에러라면 서버 내부 에러라는 얘기네요.
@PreAuthorize를 붙인 이후 에러가 나셨다고 하셨네요..
우선은 Postman 등에서 JWT 전송이 제대로 되었는지 확인하는게 필요합니다.
서버 쪽에서는
JWTFilter에서 예외가 발생하지 않는지 확인하시고
@EnableMethodSecurity(prePostEnabled = true)
설정이 필요한데 있는지 확인해 보셔야 할 듯 합니다.
강의와 동일한 예제로 작성하셨다면 백엔드 코드를 cookie_00@naver.com로 알려주시면 테스트해 볼 수 있습니다.
0
섹션7번 처음부터 다시 들어보니, MemberDTO에서 ""ROLE+str이 되어야 하는데, "Role"+str로 타이핑이 되어있었습니다... 그래도 답변해주셔서 감사합니다!
0
안녕하세요, tobot222님. 인프런 AI 인턴입니다.
@PreAuthorize와 연관된 문제는 보통 사용자 인증 및 권한 설정과 관련된 부분에서 발생할 수 있습니다. 설명해주신 상황으로 봤을 때, 사용자의 역할이나 권한 정보가 제대로 설정되지 않아서 발생하는 문제일 가능성이 높습니다. 몇 가지 점검 사항과 해결 방법을 제안드립니다.
1. JWTCheckFilter에서의 문제
JWT Claims 확인:
JWTUtil.validateToken(accessToken)에서 반환되는claims맵에 사용자의 역할(roleNames) 정보가 제대로 포함되어 있는지 확인이 필요합니다.claims맵에roleNames가 리스트 형식으로 포함되어 있어야@PreAuthorize어노테이션이 작동할 수 있습니다.roleNames리스트에 사용자의 권한이 제대로 셋업되어 있는지 로그를 찍어 확인해보세요.
Authentication 설정:
UsernamePasswordAuthenticationToken을 생성할 때, 사용자 권한 정보가 올바르게 전달되는지 확인하세요.- 생성된
authenticationToken에 사용자의 권한이 제대로 설정되어야 합니다.
- 생성된
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(memberDTO, pw, memberDTO.getAuthorities());
2. CustomSecurityConfig 설정 확인
@EnableMethodSecurity설정: 이미@EnableMethodSecurity를 사용하고 계시지만, 꼭CustomSecurityConfig내의 다른 설정도 적절하게 되어 있는지 확인하세요.
3. 기타 확인 사항
토큰 발급 시 역할 정보 포함: JWT 토큰을 발급할 때
claims에 사용자의 권한 정보가 포함되어야 합니다. 이 정보가 빠져 있는 경우,@PreAuthorize검증이 실패할 수 있습니다.HTTP 헤더 설정: Postman으로 요청을 보낼 때 Authorization 헤더에
Bearer토큰이 제대로 포함되어 있는지도 확인하세요. 토큰의 형식이 잘못되면 인증에 실패할 수 있습니다.
참고 답변 링크
- JWT 체크 필터 적용 후 상품 목록 조회 …: 토큰 사용의 일반적인 문제와 두 번 호출되는 문제에 대한 내용이 있습니다.
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서도 답변을 확인하시고 추가적인 도움을 드릴 수 있을 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해 드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
동일하게 실습하는데 이상하게 페이지를 찾지 못하네요..
0
74
2
22. REST 방식 컨트롤러 만들기(2), 29. 등록처리 부분 질문이 있습니다.
0
74
2
37강. 강의수업듣다 질문드립니다.
0
57
2
TodoDTO test 함수
0
80
3
강사님 오타 있음요
0
77
2
No 1. 교제(ppt) soruce 복붙 문제 의 건
0
95
4
No 1. 교제(ppt) soruce 복붙 문제 의 건
0
70
3
17강 문의드립니다.
0
44
1
카카오 연동설정이 이제 안되는거 같아요
0
190
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
291
2
엔티티클래스에서 질문입니다
0
78
2
수정시 writer값이 삭제되는 오류
0
42
2
교안 31 오타 수정해주세요
0
64
2
쿠키에 accessToken, refreshToken을 담고, 조회 시에 undefined
0
80
1





