본문 바로가기
서버구축 (WEB,DB)

DBMS 사용자 SQL 쿼리 실행 전 권한을 검증하는 로직 구현

by 날으는물고기 2024. 6. 30.

DBMS 사용자 SQL 쿼리 실행 전 권한을 검증하는 로직 구현

Authorization and Integrity Manager in DBMS - GeeksforGeeks

SQL 쿼리에 대한 사용자 권한을 체크하는 방법을 구현하려면, 우선 사용자의 권한을 정의하고, SQL 쿼리를 실행하기 전에 이러한 권한을 검증하는 과정이 필요합니다. 이는 대체로 데이터베이스 시스템에서 제공하는 기능을 사용하거나, 어플리케이션 레벨에서 별도의 로직을 구현하여 관리할 수 있습니다.

권한 정의

  • 사용자별 권한: 각 사용자(또는 사용자 그룹)가 특정 테이블 또는 컬럼에 대해 수행할 수 있는 작업(조회, 수정, 삭제 등)을 정의합니다.
  • 테이블 권한: 각 테이블에 대해 어떤 사용자가 어떤 작업을 할 수 있는지 정의합니다.
  • 컬럼 권한: 테이블 내 특정 컬럼에 대한 접근을 제한할 수 있습니다.

권한 검증 방법

데이터베이스 기능 사용

대부분의 관계형 데이터베이스 관리 시스템(RDBMS)은 권한 관리 기능을 내장하고 있습니다. SQL 표준에 따라 GRANTREVOKE 문을 사용하여 사용자에게 특정 테이블이나 컬럼에 대한 권한을 부여하거나 철회할 수 있습니다.

-- 사용자에게 테이블에 대한 SELECT 권한 부여
GRANT SELECT ON table_name TO user_name;

-- 사용자에게 테이블에 대한 UPDATE 권한 부여
GRANT UPDATE ON table_name TO user_name;

-- 사용자에게 특정 컬럼에 대한 DELETE 권한 부여
GRANT DELETE (column_name) ON table_name TO user_name;

어플리케이션 레벨에서 권한 체크

어플리케이션 코드 내에서 사용자의 요청을 검사하여 권한을 체크하는 로직을 구현할 수 있습니다. 이 경우, 권한 정보를 저장할 데이터베이스 테이블을 디자인하고, 사용자의 요청과 이 테이블을 비교하여 권한을 검증합니다.

CREATE TABLE permissions (
    user_id INT,
    table_name VARCHAR(255),
    permission_type VARCHAR(50), -- 예: 'SELECT', 'UPDATE', 'DELETE'
    column_name VARCHAR(255) -- NULL이면 전체 컬럼에 대한 권한
);

권한 체크 로직 예시

-- 사용자가 특정 테이블에 대해 SELECT 권한을 가지고 있는지 체크
SELECT EXISTS (
    SELECT 1
    FROM permissions
    WHERE user_id = :user_id
      AND table_name = :table_name
      AND permission_type = 'SELECT'
);

이와 같이 SQL 쿼리 실행 전에 사용자의 권한을 확인하는 과정을 통해 데이터의 보안을 강화하고, 무단 접근을 방지할 수 있습니다.

 

SQL 쿼리를 실행하기 전에 특정 사용자의 권한을 검증하는 코드를 작성하는 예시는 여러 프로그래밍 언어로 구현할 수 있습니다. 여기서는 Python을 사용하여 사용자의 ID와 SQL 쿼리를 파라미터로 받아 권한을 검증하는 함수를 만드는 방법을 설명하겠습니다.

권한 검증 함수

Python에서 sqlite3 모듈을 사용하여 SQLite 데이터베이스를 예로 들어 권한 검증 함수를 구현할 수 있습니다. 이 예시는 사용자 ID와 SQL 쿼리 문자열을 입력으로 받고, 해당 사용자가 쿼리를 실행할 권한이 있는지 여부를 반환합니다.

import sqlite3
import re

def check_permission(user_id, query):
    # SQLite 데이터베이스 연결
    conn = sqlite3.connect('your_database.db')
    cursor = conn.cursor()

    # 쿼리 타입과 테이블 이름 추출
    query_type = query.split()[0].upper()  # 예: 'SELECT', 'UPDATE', 'DELETE'
    table_name_match = re.search(r'FROM\s+(\w+)', query, re.IGNORECASE)
    table_name = table_name_match.group(1) if table_name_match else None

    if not table_name:
        raise ValueError("테이블 이름을 쿼리에서 찾을 수 없습니다.")

    # 권한 검증 쿼리
    cursor.execute("""
        SELECT COUNT(*)
        FROM permissions
        WHERE user_id = ?
          AND operation = ?
          AND table_name = ?
          AND (column_name IS NULL OR column_name = '')  -- 컬럼 권한이 없는 경우도 포함
    """, (user_id, query_type, table_name))

    # 권한이 있는지 확인
    permission_count = cursor.fetchone()[0]

    # 데이터베이스 연결 종료
    conn.close()

    # 권한이 있으면 True, 없으면 False 반환
    return permission_count > 0

# 사용 예시
user_id = 1
query = "SELECT * FROM users"
if check_permission(user_id, query):
    print("권한이 있습니다.")
else:
    print("권한이 없습니다.")

주의사항

  • 위 코드는 SQL 인젝션 공격에 취약하지 않도록 쿼리 파라미터를 바인딩하는 방식을 사용합니다.
  • re.search를 사용하여 SQL 쿼리에서 테이블 이름을 추출하는 방식은 간단한 쿼리에서만 작동하며, 복잡한 쿼리 또는 서브쿼리를 포함하는 경우에는 추가 로직이 필요할 수 있습니다.
  • 실제 어플리케이션에서는 데이터베이스 연결을 관리하는 더 효율적인 방법 (예: 커넥션 풀)을 사용해야 합니다.
728x90

댓글