- 인가가 실제 애플리케이션에서 어떻게 구현되는가
- 게시물 관리, API 엔트포인트 접근 제어, 관리자/일반 사용자 구분과 같은 사례 학습
- 인가 정책이 어떻게 서비스 요구사항과 연결되는가
- 시나리오를 살펴보며 추상 개념을 실제 구현으로 연결하기
- 실무에서 자주 마주치는 권한 설계 고민을 이해하고 해결법 익히기
게시물 접근 권한 관리
게시판 시스템에서 게시물(Post)은 작성자와 독자가 있고, 각 행동(읽기, 수정, 삭제)에 따라 권한이 달라진다
1. 기본 정책 정의
| 행위(action) | 권한 대상 | 설명 |
| 게시물 읽기(READ) | 모든 로그인 사용자 | 공개 게시물을 누구나 조회 가능 |
| 게시물 작성(CREATE) | 로그인 사용자 | 인증된 작성자만 작성 가능 |
| 게시물 수정(UPDATE) | 작성자 본인 | 본인의 소유 글만 수정 가능 |
| 게시물 삭제(DELETE) | 작성자 본인 / 관리자 | 작성자는 본인 글만, 관리자는 전체 삭제 |
2. 예제
커스텀 UserPrincipal.java
import com.b1uffer.sessiontest.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
public class UserPrincipal implements UserDetails {
private final User user;
public UserPrincipal(User user) {
this.user = user;
}
// 대충 오버라이드한 로직들
// isAdmin 추가
public boolean isAdmin() {
return user.getRoles().contains("ADMIN");
}
}
PostService.java
import com.b1uffer.sessiontest.entity.Post;
import com.b1uffer.sessiontest.repository.PostRepository;
import com.b1uffer.sessiontest.security.UserPrincipal;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@NoArgsConstructor
public class PostService {
private PostRepository postRepository;
public Post create(Long id, Post post) {
Post findPost = postRepository.findById(id)
.orElseThrow(() -> new RuntimeException("post not found"));
post.setContent(post.getContent());
postRepository.save(findPost);
return findPost;
}
public void update(Post post, String newContent) {
// 인증 로직
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
// 작성자 본인이거나 관리자일 때 업데이트 가능
if(!post.getOwner().equals(principal.getUsername()) || !principal.isAdmin()) {
log.info("게시글 수정 실패");
throw new IllegalArgumentException("수정 권한이 없습니다.");
}
post.setContent(newContent);
log.info("게시글 수정 완료");
}
public void delete(Post post) {
// 인증 로직
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
// 작성자 본인이거나 관리자일 때 삭제 가능
if(!post.getOwner().equals(principal.getUsername()) || !principal.isAdmin()) {
log.info("게시글 삭제 실패");
throw new IllegalArgumentException("삭제 권한이 없습니다.");
}
postRepository.delete(post);
log.info("게시글 삭제 완료");
}
}
*작성자만 수정 가능, 관리자는 예외적으로 모든 글 수정 가능 정책이 필터링 형태로 구현되어있음
3. 워크플로우 다이어그램
팁
* 게시물 권한은 작성자/관리자를 중심으로 설계하는 경우가 많다
* 서비스 확장시, 공유 게시물(팀 단위 수정)같은 새로운 요구사항이 추가될 수 있으므로 정책을 유연하게 설계하는 것이 중요함
API 엔드포인트 권한 관리
REST API를 제공하는 서비스에서는 엔드포인트마다 접근 권한이 다르다
1. 엔드포인트 정책 예
| 엔트포인트 | 권한 | 설명 |
| GET /api/users/{id} | 본인 또는 관리자 | 개인정보 보호 |
| POST /api/users | 관리자 | 신규 사용자 등록 |
| GET /api/posts | 로그인 사용자 | 글 목록 조회 |
| DELETE /api/posts/{id} | 작성자 또는 관리자 | 글 삭제 |
2. 예(API Layer)
UserController.java
import com.b1uffer.sessiontest.entity.User;
import com.b1uffer.sessiontest.security.UserPrincipal;
import com.b1uffer.sessiontest.service.UserService;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/users")
public class UserController {
private UserService userService;
@GetMapping("{username}")
public User getUser(@PathVariable String username, @AuthenticationPrincipal UserPrincipal userPrincipal) {
if(!userPrincipal.getUsername().equals(username) || !userPrincipal.isAdmin()) {
throw new SecurityException("Invalid username or password");
}
User getUser = userService.get(username);
return getUser;
}
/**
* 관리자 전용 api
*/
@PostMapping
public User createUser(@RequestBody User user, @AuthenticationPrincipal UserPrincipal userPrincipal) {
if(!userPrincipal.isAdmin()) {
throw new SecurityException("관리자만 등록 가능합니다.");
}
User createUser = userService.create(user.getUsername(), user.getPassword());
return createUser;
}
}
* 엔드포인트 권한은 API 명세 단계에서 미리 정의하는게 좋다
* 문서화된 권한 정책은 개발자, QA, 보안 담당자 모두에게 유용하니까 문서화는 꼭 해야한다. 보기 편함
관리자와 일반 사용자 권한 구분
관리자(Admin)와 일반 사용자(User)를 구분하는 것은 모든 서비스에서 필요하다
1. 역할(Role) 기반 구분
| 역할 | 권한 범위 |
| 관리자(Admin) | 시스템 설정, 모든 데이터 접근, 사용자 관리 |
| 일반 사용자(User) | 본인 데이터 접근, 서비스 기본 기능 사용 |
2. 예제
public class User {
private String id;
private String role; // "ADMIN", "USER"
public boolean isAdmin() {
return "ADMIN".equals(role);
}
}
3. 워크플로우
* 관리자 권한은 최소한의 사용자에게만 부여함
* 관리자 계정이 탈취되면 피해가 크므로 이중 인증(MFA) 같은 보안 강화 방법을 적용해야함
https://b1uffer.tistory.com/363
정리
| 구분 | 주요 내용 | 핵심 |
| 게시물 권한 관리 | 작성자, 관리자 중심의 권한 부여 | 소유자 정책, 관리자는 예외 |
| API 권한 관리 | 엔드포인트별 접근 제어 | 명세 단계에서 문서화가 필요함 |
| 관리자 / 사용자 구분 | 역할 기반 접근 제어(ADMIN, USER) | 최소 권한 부여, MFA 권장 |
'Spring Boot > 유저 관리 기능' 카테고리의 다른 글
| OAuth와 OpenID Connect : OAuth의 개념, 필요성 (0) | 2026.03.23 |
|---|---|
| 인가와 권한 관리 : 세션/토큰 기반 인증에서의 인가 구현 (0) | 2026.03.22 |
| 인가와 권한 관리 : Spring Security와 권한 검증 플로우 (0) | 2026.03.17 |
| 인가와 권한 관리 : 권한 기반 접근 제어 (0) | 2026.03.17 |
| 인가와 권한 관리 : 인가 (0) | 2026.03.15 |