[python] 파이썬 웹 개발에서의 인증과 인가 방식

웹 개발에서 인증(Authentication)과 인가(Authorization)은 중요한 보안 개념입니다. 인증은 사용자가 자신을 신원을 확인하는 것이고, 인가는 사용자가 특정 리소스에 접근할 수 있는 권한을 부여하는 것입니다. 이 글에서는 파이썬 웹 개발에서 인증과 인가를 구현하는 다양한 방식을 알아보겠습니다.

1. 기본 인증 (Basic Authentication)

기본 인증은 가장 간단한 인증 방식으로, 사용자의 신원을 확인할 때 Base64로 인코딩된 사용자 이름과 비밀번호를 서버에 전송하는 방식입니다.

from flask import Flask, request
from functools import wraps

app = Flask(__name__)

def check_auth(username, password):
    # 사용자 이름과 비밀번호를 확인하는 로직
    return username == 'admin' and password == 'password'

def require_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            return '인증이 필요합니다.', 401
        return f(*args, **kwargs)
    return decorated

@app.route('/protected')
@require_auth
def protected_route():
    return '인증된 사용자만 접근 가능한 페이지입니다.'

위의 예제에서 check_auth 함수는 사용자 이름과 비밀번호를 확인하는 로직을 구현합니다. require_auth 데코레이터는 요청의 Authorization 헤더를 확인하고, 인증되지 않은 경우 401 Unauthorized 응답을 반환합니다. /protected 경로에 적용된 require_auth 데코레이터를 확인하면, 해당 경로에 접근하려면 인증이 필요하다는 것을 알 수 있습니다.

2. 세션 인증 (Session Authentication)

세션 인증은 로그인 후에 서버 측에서 세션을 유지하는 방식입니다. 사용자의 신원을 확인한 후 세션 ID를 클라이언트에게 전달하고, 클라이언트는 이 세션 ID를 이용하여 인증 여부를 확인합니다.

from flask import Flask, request, session

app = Flask(__name__)
app.secret_key = 'your_secret_key'

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']

    # 사용자 이름과 비밀번호를 확인하는 로직
    if username == 'admin' and password == 'password':
        session['logged_in'] = True
        return '로그인 성공!'
    else:
        return '로그인 실패!'

@app.route('/protected')
def protected_route():
    if session.get('logged_in'):
        return '인증된 사용자만 접근 가능한 페이지입니다.'
    else:
        return '인증이 필요합니다.'

위의 예제에서 /login 경로는 POST 메서드로 사용자 이름과 비밀번호를 전달받아 로그인을 처리합니다. 로그인이 성공하면 sessionlogged_in 키를 True로 설정하여 세션을 유지합니다. /protected 경로에서는 세션에 logged_in 키가 있는지 확인하여 인증 여부를 판단합니다.

3. JWT 인증 (JWT Authentication)

JWT (JSON Web Token) 인증은 토큰 기반으로 동작하는 인증 방식입니다. 클라이언트는 JWT 토큰을 발급받고, 이 토큰을 이용하여 서버에 접근 권한을 요청합니다. JWT는 서버에서 발행된 서명이 포함된 토큰입니다.

import jwt
from flask import Flask, request

app = Flask(__name__)
app.secret_key = 'your_secret_key'

@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']
    password = request.form['password']

    # 사용자 이름과 비밀번호를 확인하는 로직
    if username == 'admin' and password == 'password':
        payload = {'username': username}
        token = jwt.encode(payload, app.secret_key, algorithm='HS256')
        return {'token': token}
    else:
        return '로그인 실패!'

@app.route('/protected')
def protected_route():
    token = request.headers.get('Authorization').split(' ')[1]  # Bearer 토큰에서 토큰 부분 추출
    try:
        payload = jwt.decode(token, app.secret_key, algorithms=['HS256'])
        return '인증된 사용자만 접근 가능한 페이지입니다.'
    except jwt.ExpiredSignatureError:
        return '토큰이 만료되었습니다.', 401
    except jwt.InvalidTokenError:
        return '유효하지 않은 토큰입니다.', 401

위의 예제에서 /login 경로는 POST 메서드로 사용자 이름과 비밀번호를 전달받아 로그인을 처리합니다. 로그인이 성공하면 JWT 토큰을 발급하여 클라이언트에게 반환합니다. /protected 경로에서는 요청의 Authorization 헤더에서 토큰을 추출한 후, 토큰의 유효성을 검증하여 인증 여부를 판단합니다.

참고 자료