작성
·
341
0
강사님의 강의를 통해 Jwt 와 시큐리티에 대한 공부를 수월히 할 수 있었습니다.
근데 개인적으로 이제 실습하면서 문제가 발생해서 자문을 구하고자 글을 쓰게 되었습니다.
로그인이 성공하면 토큰을 로컬 스토리지에 담고, 요청할 때는 토큰을 꺼내어 헤더에 담아서 검증절차를 진행하려고 합니다.
근데 분명 위의 프로세스에 해당 하는 로직을 작성하였다고 생각하였는데, 의도한 대로 흘러가지가 않아서 매우 난처한 상황입니다.
Index.html
<script>
$(document).ready(function() {
// 로그아웃 버튼 이벤트
$('#logoutButton').click(function() {
// 로컬 스토리지에서 토큰 제거
localStorage.removeItem('accessToken');
// 로그인 페이지로 리다이렉션
window.location.href = '/login';
});
// 테스트 버튼 이벤트
$('#testButton').click(function() {
// 로컬 스토리지에서 토큰 가져오기
const token = localStorage.getItem('accessToken');
if (token) {
$.ajax({
url: '/api/test', // 요청할 서버의 URL
type: 'GET', // HTTP 메서드
beforeSend: function(xhr) {
// 요청 헤더에 토큰 추가
xhr.setRequestHeader('Authorization', token);
},
success: function(data) {
// 요청 성공 시 로직
console.log("테스트 요청 성공:", data);
alert("테스트 요청 성공");
},
error: function(xhr, status, error) {
// 요청 실패 시 로직
console.error("테스트 요청 실패:", xhr.responseText);
alert("테스트 요청 실패");
}
});
} else {
alert("토큰이 없습니다. 다시 로그인해주세요.");
}
});
});
</script>
이와 같이 /url/test 로 api 요청을 할때 헤더에 토큰을 담게 했습니다.
이에 "테스트 버튼"을 누르게 되면
JwtAuthorizationFilter
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws ServletException, IOException {
// 헤더에서 토큰 추출
log.info("헤더에서 토큰 추출");
String tokenValue = jwtUtil.getJwtFromHeader(req);
log.info("토큰 : " + tokenValue);
if (StringUtils.hasText(tokenValue)) {
// 토큰 유효성 검사
if (!jwtUtil.validateToken(tokenValue)) {
log.info("Token Error");
return;
}
Claims info = jwtUtil.getUserInfoFromToken(tokenValue);
try {
setAuthentication(info.getSubject());
} catch (Exception e) {
log.error(e.getMessage());
return;
}
}
else {
log.info("토큰이 없습니다.");
}
filterChain.doFilter(req, res);
}
// 인증 처리
public void setAuthentication(String loginId) {
log.info("인증 성공");
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication = createAuthentication(loginId);
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
}
// 인증 객체 생성
private Authentication createAuthentication(String loginId) {
log.info("인증 객체 생성");
UserDetails userDetails = userDetailsService.loadUserByUsername(loginId);
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
}
로그로 토큰이 출력되는 것과 최종적으로 인증 객체 생성까지 되는 것을 확인했습니다.
그러나 이렇게 인가 필터를 거치고 이제 컨트롤러로 접근하게 되면
@GetMapping("/api/test")
public String testPage() {
log.info("test controller");
return "test";
}
저기 test controller 라는 로그만 찍힌채 프로세스가 마무리됩니다.
최종로그
2024-02-26T16:19:36.394+09:00 INFO 60592 --- [nio-8081-exec-9] JWT 검증 및 인가 : 토큰 : eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0NiIsImF1dGgiOiJPV05FUiIsImlhdCI6MTcwODkzMTk3MywiZXhwIjoxNzA4OTM1NTczfQ.A2AhGDg5phTcm4gGC-01K0jKoAGE1c5Ygsq9v_J1ntk
2024-02-26T16:19:36.426+09:00 INFO 60592 --- [nio-8081-exec-9] JWT 검증 및 인가 : 인증 성공
2024-02-26T16:19:36.427+09:00 INFO 60592 --- [nio-8081-exec-9] JWT 검증 및 인가 : 인증 객체 생성
Hibernate:
/* <criteria> */ select
u1_0.id,
u1_0.email,
u1_0.login_id,
u1_0.password,
u1_0.role
from
users u1_0
where
u1_0.login_id=?
2024-02-26T16:19:36.434+09:00 INFO 60592 --- [nio-8081-exec-9] TestController : test controller
이때 웹 페이지의 개발자 도구를 열어서 콘솔로그를 확인 해보면, 제가 가지고 오고자 했던 test.html 의 코드만이 적혀있을 뿐입니다.
뭐가 문제인 걸까요..
혹시나 test 쪽에 토큰을 가져오는 로직도 작성해봤습니다.
Test.html
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.7.0.min.js"
integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script>
<script>
$(document).ready(function () {
const auth = getToken();
if (auth) {
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
jqXHR.setRequestHeader('Authorization', auth);
});
} else {
window.location.href = '/user/login-page';
}
});
function getToken() {
let auth = localStorage.getItem('accessToken');
return auth || '';
}
</script>
<title>Test Page</title>
</head>
<body>
<h1>This is a test page.</h1>
</body>
</html>
그럼에도 여전히 해당 페이지에는 접근을 못하고 있습니다 ㅠㅠㅠㅠ
제가 놓친 부분이 뭐가 있을지 조언을 주신다면 감사하겠습니다.
답변 2
0
0
안녕하세요, 인프런 AI 인턴입니다.
모코코님, 스프링 부트와 JWT를 활용한 보안 관련하여 실습 중 문제가 생겨 고민이 많으시군요. 문제를 해결하기 위해 몇 가지 가능성을 살펴보겠습니다.
Authorization: Bearer {token}
과 같아야 한다는 점을 확인해 주세요.test
라는 문자열이 그대로 반환되고 있는 것으로 보입니다. 만약 test.html
페이지를 반환하고자 한다면 Thymeleaf나 JSP와 같은 템플릿 엔진을 사용하고 있지 않는다면, return "redirect:/test.html";
과 같이 리다이렉트를 사용하거나 ModelAndView
객체를 사용하여 뷰 이름을 설정하는 방식을 사용해야 합니다.위의 가능성들을 하나씩 확인해가며 문제를 해결해보시기를 바랍니다. 추가적으로 필요하다면, 스프링 시큐리티의 테스트 관련 문서를 참고하실 수 있습니다. Spring Security Reference Documentation에서 더 자세한 정보를 얻으실 수 있습니다. 혹시나 설정이나 코드에 더 궁금한 점이 있다면 질문해 주세요.