평소와 같이 하루를 보내던 도중 지인한테 연락이 왔다. 진행하던 개인 프로젝트 도중에 자꾸 401 에러가 떠서 한번 봐달라고 해서 집으로 돌아와 코드를 확인하고 해당 지인의 에러를 해결했다. 개발이 항상 그렇듯, 사소한거에서 틀리거나 놓쳐서 되게 어이없는 경우가 많은데 이번에도 그랬다. 아무튼 이번 기회를 삼아 이번 에러를 해결하기까지의 과정과 401 / 403에 대해 조금 자세히 정리해보려 한다.
💡 상태코드 401과 403이 헷갈려요!
상태코드 401과 403은 인증되지 않은 사용자라는 공통점이 있어 헷갈리지만 인증이 왜(why) 되지 않았냐에 집중하면 쉽게 나눠진다. 각각의 상태코드에 대한 설명을 먼저 살펴보자.
🤔 401 과 403의 왜(Why?)
상태코드 401이 왜(why) 표시되나면 사용자가 어떠한 방식(ex.로그인)을 통해 자격 증명을 얻지 않고 자격 증명이 필요한 페이지에 접근하려 해서이다. 대신 계속해서 인증이 가능하다.
그에 반해 403이 왜(why) 표시되는 이유는 로그인을 하였더라도 자격 증명이 일반 유저로 제공되어있음에도 관리자 자격 증명이 필요한 페이지에 접근하려해서이다. 그렇기 때문에 페이지가 원하는 권한이 아닌 경우 재인증을 하더라도 지속적으로 접속을 거부하게 되어 인증이 불가능하다.
일단 위의 내용처럼 자격 증명을 얻지 않고 자격 증명이 필요한 요청을 해서이다.
지인의 코드는 로그인을 하는 API가 자꾸 자격 증명을 필요로 해서 문제가 발생했고 당연하게도 로그인 API는 분명 자격 증명이 필요없이 전체 허용이 되어야 하는 API 이기 때문에 수정이 필요했다.
에러를 해결하기 위해 필자가 먼저 확인했던 항목들은 아래와 같다.
.antMatchers("/auth/signup", "/auth/signin").permitAll()
API 주소나 설정 관련 코드들은 문제가 없어 Service 클래스 에서 로그를 찍어보았고 해당 부분에서 코드가 제대로 작동되지 않는 것을 확인하였다.
Authentication authentication = authenticationManagerBuilder
.getObject()
.authenticate(authenticationToken);
SecurityContextHolder
.getContext().setAuthentication(authentication);
로그인을 할때 Authentication을 생성하는 과정에서 문제가 발생되었기 때문에 세부 로직을 살펴봤다.
혹시 필터 부분에 문제가 있을 수도 있어
해보았지만 해당 부분에서도 문제점을 찾지 못하였고 미궁속으로 빠졌다 🤔
회원가입 API는 잘 작동되는 것을 확인하였기 때문에 역시 로그인 로직에서 문제가 발생된다는 걸 인지하고 있었고 로그인 로직과 관련된 코드와 클래스, 세부 항목들을 살펴보았고 점점 더 어려워졌다.
💡 그러면 대체 뭐가 문제였을까 ?
로그인 로직에서의 코드를 확인을 해보아도 문제점이 발견되지 않아 미궁속으로만 빠져가다가 아래 코드의 Entity를 확인해보게 되었다. 그리고 바로 문제점을 찾았다.
엔티티에서 문제가 있을거라 생각도 못했고 User클래스에 빨간줄이 그어져있었지만 서버가 정상적으로 돌아가 확인이 힘들었던 것 같다.
@Entity
@Getter
@Setter
@Builder
@Table(name = "user_table")
public class User extends BaseTimeEntity {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long id;
문제는 기본생성자와 전체 컬럼을 파라미터로 받는 생성자가 존재하지 않아서였다.
엔티티 내부에서 @AllArgsConstructor, @NoArgsConstructor 를 통해 생성자를 만들어주거나, 또는 코드를 통해 생성자를 만들어주지만 해당 엔티티에서는 생성자를 만들어주는 어노테이션이나 코드가 존재하지 않았다.
그럼에도 서버는 잘 돌아갔기 때문에 이 부분이 빠졌을거라곤 생각을 못했던 것 같다 😰
이렇듯 401과 403은 인증과 권한에 대한 부분이기 때문에 SecurityConfig와 같이 권한을 허용해주는 부분에서의 문제가 아니라면, 분명 단순한 실수인 문제가 많은 것 같다. 필자도 프로젝트를 개발할때 401을 봐왔었고 아주 단순한 코드 실수로 401 문제를 겪었었다.
개발을 하면서 항상 느끼는건 에러는 정말 단순한 실수나 문제로 코드가 제대로 돌아가지 않는 경우가 대부분인것 같다. 지인 또한 해당 코드를 보고 엔티티를 늘 그렇듯 생성하다가 어노테이션을 빼먹은 것 같다고 하였다. 😉
그럼 이번 포스팅은 여기서 끄읏-!