[데브코스] Spring Boot 인증·인가(Auth) (28강) - 글 삭제 시 Authorization 인증 + 작성자 권한 체크(인가) 추가

zuno·2026년 1월 13일

이번 강의에서는 글 삭제(DELETE) API에도 인증 정보를 전달하고,
삭제 요청자가 해당 글의 작성자인지 권한 체크(인가) 를 추가했다.


✅ 변경 요약

  • DELETE /api/v1/posts/{id} 요청에서도 Authorization 헤더(Bearer apiKey) 를 받도록 수정
  • apiKey로 사용자(actor)를 찾고
  • actor == 글 작성자(author) 인지 확인해서
    • 아니면 403 (권한 없음)
    • 맞으면 삭제 진행

🧩 컨트롤러 코드 변경

✅ Before

  • 삭제는 id만 받아서 바로 삭제
public RsData<Void> delete(@PathVariable int id) {
    ...
}

✅ After

  • Authorization 헤더를 함께 받고
  • 인증 + 인가 로직을 추가
@DeleteMapping("/{id}")
@Transactional
@Operation(summary = "삭제")
public RsData<Void> delete(
        @PathVariable int id,
        @NotBlank @Size(min = 30, max = 50)
        @RequestHeader("Authorization") String authorization
) {
    String apiKey = authorization.replace("Bearer ", "");
    Member actor = memberService.findByApiKey(apiKey)
            .orElseThrow(() -> new ServiceException("401-1", "존재하지 않는 apiKey 입니다."));

    Post post = postService.findById(id).get();

    if (!actor.equals(post.getAuthor()))
        throw new ServiceException("403-1", "글 삭제 권한이 없습니다.");

    postService.delete(post);

    return new RsData<>(
            "200-1",
            "%d번 글이 삭제되었습니다.".formatted(post.getId())
    );
}

🔐 여기서 인증 / 인가가 각각 어디?

1) 인증(Authentication) — “누구냐?”

Member actor = memberService.findByApiKey(apiKey)
  • Authorization 헤더에서 apiKey를 뽑고
  • 그 apiKey로 회원을 찾는다
  • 없으면 401 (인증 실패)

2) 인가(Authorization) — “너 그 글 지울 권한 있냐?”

if (!actor.equals(post.getAuthor()))
    throw new ServiceException("403-1", "글 삭제 권한이 없습니다.");
  • 글 작성자와 요청자가 같은지 비교
  • 다르면 403 (권한 없음)

🧠 actor.equals(post.getAuthor())가 성립하는 이유

겉으로 보면

  • actor는 apiKey로 DB 조회한 Member
  • post.getAuthor()도 DB에서 연관으로 가져온 Member
  • “서로 다른 객체라서 equals가 false 아닐까?” 라고 생각할 수 있음

하지만 프로젝트의 BaseEntity에서 equals를 id(PK) 기준으로 비교하게 구현되어 있다.

@Override
public boolean equals(Object o) {
    if (o == this) return true;
    if (o == null || getClass() != o.getClass()) return false;
    BaseEntity that = (BaseEntity) o;
    return id == that.id;
}

✅ 그래서 객체 인스턴스가 달라도
같은 엔티티 + 같은 id면 equals가 true가 된다.


🧪 테스트 코드도 Authorization 헤더로 변경

삭제 테스트에서도

  • 예전처럼 쿼리 파라미터로 apiKey를 붙이지 않고
  • .header("Authorization", "Bearer " + actorApiKey) 형태로 맞춰줬다.
ResultActions resultActions = mvc
        .perform(
                delete("/api/v1/posts/" + id)
                        .header("Authorization", "Bearer " + actorApiKey)
        )
        .andDo(print());

✨ 정리

  • DELETE 요청에도 인증 정보는 Authorization 헤더로 전달
  • 삭제는 “로그인만”으로 충분하지 않음 → 작성자 권한 체크(인가) 필요
  • actor.equals(post.getAuthor())는 BaseEntity의 equals가 PK(id) 기준이라서 정상 동작

0개의 댓글