인프런 커뮤니티 질문&답변
JWT와 @PreAuthorize 사용하기에서 권한오류
작성
·
132
0
동영상 강의에 있는 내용대로 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
안녕하세요, 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 체크 필터 적용 후 상품 목록 조회 …: 토큰 사용의 일반적인 문제와 두 번 호출되는 문제에 대한 내용이 있습니다.
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서도 답변을 확인하시고 추가적인 도움을 드릴 수 있을 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해 드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏






섹션7번 처음부터 다시 들어보니, MemberDTO에서 ""ROLE+str이 되어야 하는데, "Role"+str로 타이핑이 되어있었습니다... 그래도 답변해주셔서 감사합니다!