본문 바로가기

Spring Boot

인가/권한 관리 : 인가 구현 예시

실제 인가 구현 사례..라고 하니깐 따라해보자

 

 - 인가(Authorization)가 실제 애플리케이션에서 어떻게 구현되는가

 - 게시물 관리, API 엔드포인트 접근 제어, 관리자/일반 사용자 구분 사례 등..

 - 인가 정책이 어떻게 서비스 요구사항과 연결되는가

 - 추상 개념을 실제 구현으로 연결하기

 - 실무에서 자주 마주치는 권한 설계 고민 이해

 

 

게시물 접근 권한 관리

게시물(Post)은 작성자와 독자가 있고, 각 행동(읽기, 수정, 삭제)에 따라 권한이 달라짐

 

1. 기본 정책 정의

행위(Action) 권한 대상 설명
게시물 읽기(Read) 모든 로그인 사용자 공개 게시물은 누구나 조회 가능함
게시물 작성(Create) 로그인 사용자 인증된 사용자만 작성 가능함
게시물 수정(Update) 작성자 본인 본인 소유글만 수정 가능함
게시물 삭제(Delete) 작성자 본인/관리자 작성자는 본인 글만, 관리자는 전체 삭제

 

2. 예제

public class PostService {
	public void updatePost(Post post, String newContent) {
    	Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 인증
        CustomUserprincipal principal = (CustomUserPrincipal)authentication.getPrincipal();
        
            // 작성자가 아니거나 관리자가 아니라면, 수정할 수 없다
        if(!post.getAuthorId().equals(principal.getUserId()) && !principal.isAdmin()) {
            throw new SecurityException("수정 권한이 없음!");
        }
        post.setContent(newContent); // 수정함
    } // updatePost 끝
    
    public void deletePost(Post post) {
    	Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // 인증
        CustomUserPrincipal principal = (CustomUserPrincipal)authentication.getPrincipal();
        
        if(!post.getAuthorId().equals(principal.getUserId()) && !principal.isAdmin()) { // 인가?
        	throw new SecurityException("삭제 권한이 없습니다.");
        }
        // 삭제하는 로직 작성
    }
}

 

if문을 통해 작성자, 관리자만 메서드를 통과할 수 있게 처리한다..

 

3. 워크플로우 다이어그램

인증, 인가를 활용하는 워크플로우, 안보이면 클릭할 것

 

* 게시물 권한은 작성자, 관리자를 중심으로 설계하는게 일반적이다

* 서비스 확장 시, 공유 게시물(팀 단위 수정) 같은 새로운 요구사항이 추가될 수 있기 때문에 정책을 유연하게 설계하는 게 중요함

 

 

API 엔드포인트 권한 관리

REST API를 제공하는 서비스에서는 엔드포인트마다 접근 권한이 다르다고 한다..

 

1. 예시 엔드포인트 정책

엔드포인트 권한 설명
GET /api/users/{id} 본인 또는 관리자 개인정보 보호
POST /api/users 관리자 신규 사용자 등록
GET /api/posts 로그인 사용자 글 목록 조회
DELETE /api/posts/{id} 작성자 또는 글 관리자 글 삭제

 

 

2. 예제 코드(API Layer)

@RestController
@RequestMapping("/api/users")
public class UserController {
	@GetMapping("/{id}") // /api/users/{id}
    public User getUser(@PathVariable String id,
                        @AuthenticationPrincipal User user) {
    	if(!user.getId().equals(id) && !user.isAdmin()) {
        	throw new SecurityException("접근 권한이 없음!");
        }
        return userService.findById(id); // getUser 이름답게 Id로 조회해줌
    }
    
    @PostMapping
    public User createUser(@AuthenticationPrincipal User user,
                           @RequestBody User newUser) {
    	if(!user.isAdmin()) {
        	throw new SecurityException("관리자만 등록 가능합니다.");
        }
        return userService.create(newUser);
    }
}

 

* 엔드포인트의 권한은 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) 같은 보안 강화 방법을 적용할 수 있음