ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • FastAPI 시리즈 13화 - 사용자 권한(Role) 관리와 종속성 적용 방법
    기술과 산업/언어 및 프레임워크 2025. 6. 2. 10:12
    728x90

    FastAPI에서 사용자 역할(Role)을 기반으로 접근 권한을 제어하는 방법을 설명합니다. Depends를 활용해 인증과 권한 검증을 모듈화하고, 실무에서 필요한 보안 구조를 구축합니다.

    왜 Role 기반 권한 관리가 필요한가?

    대부분의 서비스는 사용자 유형이 나뉘며 각자의 권한이 다릅니다:

    사용자 유형 접근 가능한 리소스

    일반 사용자 본인의 정보, 게시글
    관리자 전체 사용자 목록, 설정 변경
    운영자 일부 모니터링 기능

    이러한 역할(Role) 기반 권한 관리 시스템은 서비스 품질뿐만 아니라 보안을 위해서도 반드시 필요합니다.


    1. JWT 토큰에 Role 정보 포함

    def create_access_token(data: dict):
        payload = data.copy()
        payload.update({
            "exp": datetime.utcnow() + timedelta(minutes=30),
            "role": data.get("role", "user")
        })
        return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
    
    • JWT의 Payload에 role 필드 포함
    • 이 필드를 기준으로 API 접근 제어 가능

    2. 사용자 인증 + 권한 검증 종속성 구성

    from fastapi import Depends, HTTPException, status
    
    def get_current_user(token: str = Depends(oauth2_scheme)):
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            username = payload.get("sub")
            role = payload.get("role", "user")
            if username is None:
                raise HTTPException(status_code=401, detail="Invalid token")
            return {"username": username, "role": role}
        except JWTError:
            raise HTTPException(status_code=401, detail="Token validation failed")
    
    • 인증만 수행
    • 반환 객체에 username, role 포함

    3. 권한 레벨별 접근 제어

    def role_required(required_roles: list[str]):
        def checker(user=Depends(get_current_user)):
            if user["role"] not in required_roles:
                raise HTTPException(
                    status_code=status.HTTP_403_FORBIDDEN,
                    detail=f"권한이 없습니다. ({user['role']} 등급은 허용되지 않음)"
                )
            return user
        return checker
    
    • 재사용 가능한 권한 검사 의존성 함수
    • 원하는 권한 목록을 매개변수로 넘겨줄 수 있음

    4. 엔드포인트별 권한 적용

    @app.get("/users/me")
    def read_my_info(user=Depends(get_current_user)):
        return {"message": f"{user['username']}의 정보입니다."}
    
    @app.get("/admin/dashboard")
    def admin_dashboard(user=Depends(role_required(["admin"]))):
        return {"message": f"관리자 {user['username']}님 환영합니다."}
    
    @app.get("/moderator/tools")
    def moderator_tools(user=Depends(role_required(["admin", "moderator"]))):
        return {"tools": ["ban_user", "monitor_activity"]}
    
    • /users/me는 인증된 모든 사용자 접근 가능
    • /admin/dashboard는 admin만 접근 가능
    • /moderator/tools는 admin, moderator 접근 가능

    5. Swagger UI에서 Role 테스트 방법

    1. /token 엔드포인트로 JWT 발급 시 role 값을 달리 설정
    2. Swagger UI의 "Authorize" 기능으로 토큰 입력
    3. 각 API 접근 시 권한 오류 여부 확인 (403 Forbidden)

    예:

    {
      "access_token": "eyJhbGci...",
      "token_type": "bearer",
      "role": "user"
    }
    

    6. 실무 확장 방향

    기능 설명

    Role Enum화 enum.RoleEnum을 사용해 역할 제한 명확화
    계정별 정책 저장 DB에 Role 필드 포함 (사용자별 롤 관리)
    상세 권한 분기 action, resource 기반 ACL 구현 가능
    로그 기록 권한 오류 발생 시 감사 로그 저장

    정리 – 인증과 권한은 분리하되, 함께 조정되어야 한다

    FastAPI에서 Role 기반 권한 관리는 다음과 같은 구조로 정리할 수 있습니다:

    1. JWT에 Role 포함
    2. get_current_user → 인증 처리
    3. role_required() → 권한 체크
    4. Depends로 조합하여 엔드포인트별 권한 차등 적용

    이 구조는 FastAPI의 종속성 주입 시스템과 자연스럽게 맞물려
    명확하고 유지보수하기 좋은 권한 시스템을 완성해줍니다.


    다음 글 예고

    FastAPI 시리즈 14화 - CORS 설정과 보안 헤더 적용하기
    에서는 외부 프론트엔드 서비스와 연동 시 반드시 설정해야 하는
    CORS 허용 정책과 보안 헤더 구성 전략을 다룹니다.

    728x90
Designed by Tistory.