시작에 앞서
해당 내용은 <가장 빠른 풀스택을 위한 Flask & FastAPI>, Dave Lee 지음. BJ Public 출판.
내용을 토대로 작성되었습니다. 보다 자세한 사항은 해당 교재를 참고하시기 바랍니다.
세션과 쿠키
- 세션: 서버 측에서 사용자의 상태 정보를 유지한다. 사용자가 웹 애플리케이션에 로그인하면 서버는 고유한 세션 ID를 생성하고 이를 쿠키로 클라이언트에게 전송한다. 클라이언트는 이 세션 ID를 가진 쿠키를 사용해 이후 요청에서 자신을 인증하고, 서버는 이 ID를 이용해 사용자의 세션 데이터에 접근한다. 세션 데이터는 비교적 민감한 정보를 포함할 수 있다. (로그인 정보, 사용자의 권한, 구매한 상품 목록 등)
- 쿠키: 클라이언트 측애서 관리되는 작은 데이터 조각이다. 웹 서버는 HTTP 응답을 통해 클라이언트에 쿠키를 전송하고, 이후 클라이언트는 동일한 서버에 HTTP 요청을 할 때마다 쿠키를 함께 전송한다. 쿠키는 주로 사용자의 선호도, 세션 식별, 트래킹 정보 등을 저장하는 데 사용된다. 예를 들어, 웹사이트는 사용자가 사이트에 방문할 때마다 로그인을 요구하지 않고 쿠키에 저장된 섹션 식별자를 통해 사용자를 인식할 수 있다.
세션과 쿠키는 웹 애플리케이션에서 사용자의 상태를 관리하는 데 사용되는 주요 기술이다.
세션과 쿠키의 필요성
- 상태유지: 사용자가 로그인 상태를 유지하거나 쇼핑 사이트에서 장바구니 정보를 보관해야 할때 유용하다
- 사용자 경험 향상: 쿠키는 사용자가 사이트 설정(언어 선택, 테마 등)을 변경했을 때 이러한 정보를 저장하여 다음 방문 때 같은 설정을 유지할 수 있게 도와준다. 이로 인해 개인화된 사용자 경험이 가능해진다.
- 보안과 관리 용이성: 세션 정보는 서버에 저장되므로 쿠키에 비해 더 안전하게 정보를 관리할 수 있다.
- 트래킹과 분석: 쿠키를 통해 사용자의 웹사이트 사용 패턴이나 방문 빈도를 추적할 수 있어 마케팅 및 사용자 분석 데이터로 활용될 수 있다.
보안이 중요한 정보는 세션을 통해, 지속적인 사용자 인식이나 선호 설정 같은 정보는 쿠키를 통해 관리하는 것이 일반적이다.
플라스크에서의 세션 사용법
플라스크 애플리케이션에서 세션을 안전하게 사용하기 위해서는 SECRET_KEY 설정이 필수이다. 플라스크의 SECRET_KEY는 세션을 암호화하기 위한 중요한 설정으로, 임의의 값으로 설정할 수 있다.
(실제 운영 환경에서는 SECRET_KEY를 보다 안전하게 관리하는 것이 일반적이다.)
SECRET_KEY는 외부로부터 세션 데이터의 안전을 보장하기 위해 필요하며, 해커가 쿠키를 복호화하여 세션 데이터를 훔치는 것을 방지한다.
from flask import session, Flask
app = Flask(__name__)
# 여기서 'your_secret_key는 실제로는 안전하게 괸리되어야 하는 민감정보
app.secret_key = 'your_secret_key'
# 세션 데이터 설정 라우트
@app.route('/set_session')
def set_session():
session['username'] = 'John'
return '세션에 사용자 이름이 설정되었습니다'
세션에 저장된 데이터는 session 객체를 통해 언제든지 접근할 수 있다. 이때 get() 메서드를 사용하면 키가 존재하지 않을 경우 None을 반환하여 에러를 방지할 수 있다.
# 세션 가져오기 라우트
@app.route('/get_session')
def get_session():
username = session.get('username')
if username:
return f'사용자 이름: {username}'
else:
return '사용자 이름이 세션에 설정되지 않았습니다'
새로운 /protected 라우트는 사용자가 세션에 있는지 없는지를 체크한다.
@app.route('/protected')
def protected():
# 세션에 'username'이 설정되어 있지 않으면 403 Forbidden 에러 반환
if 'username' not in session:
abort(403)
return '이 페이지는 로그인한 사용자만 볼 수 있습니다'
else:
return '로그인된 페이지입니다'
http://127.0.0.1:5000/protected 페이지를 방문할 때 세션에 'username'이 설정되어 있어야만 페이지를 볼 수 있다.
[플라스크 주요 session 객체 사용법]
1. 세션 데이터 저장하기
session['user_id'] = 42
사용자의 ID를 세션에 저장한다. 이 ID는 로그인 시 할당된 고유한 값일 수 있다.
2. 세션 데이터 조회하기
user_id = session.get('user_id')
세션에서 user_id를 조회한다. user_id가 없다면 None 반환
3. 세션 데이터 삭제하기
session.pop('user_id', None)
user_id 키를 가진 세션 데이터를 삭제한다. 두 번째 인자는 키가 존재하지 않을 경우 반환할 기본값이다.
4. 세션 데이터의 존재 여부 확인하기
is_logged_in = 'user_id' in session
'user_id'가 세션에 존재하는지 확인. 로그인 여부를 체크하는 데 사용할 수 있다.
5. 세션의 모든 데이터 삭제하기
session.clear()
세션의 모든 데이터를 삭제. 로그아웃 기능을 구현할 때 유용하다.
6. 세션 데이터가 수정되었음을 명시하기
session.modified = True
세션 데이터가 수정되었음을 플라스크에 알린다. 이는 세션의 내용이 변경될 때 자동으로 플라스크가 처리하지 못하는 경우에 유용하다.
플라스크에서의 쿠키 사용법
사용자에게 쿠키를 설정하려면 응답 객체에 set_cookie() 메서드를 사용한다. (쿠키 이름과 값 지정 가능)
쿠키 설정을 위해 make_response를 사용하는 이유는 플라스크에서 쿠키를 설정하기 위해서는 HTTP 응답 객체가 필요하기 때문이다. 기본적으로 라우트 함수는 문자열을 반환하며, 플라스크는 이를 HTTP 응답으로 변환한다.
하지만 쿠키를 설정하려면 단순히 문자열이 아닌 수정이 가능한 응답 객체를 다뤄야 한다.
make_response() 함수는 라우트 함수의 반환값을 받아서 플라스크의 응답 객체를 생성한다. 이 객체를 사용하여 HTTP 헤더를 설정하거나 쿠키를 추가하는 등의 추가적인 작업을 수행할 수 있다.
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/set_cookie')
def set_cookie():
resp = make_response('쿠키를 설정합니다')
resp.set_cookie('username', 'John')
return resp
설정된 쿠키는 요청 객체의 cookies 속성을 통해 조회할 수 있다. 이는 딕셔너리 형태이며, 키를 사용하여 값을 읽어올 수 있다.
플라스크에서는 request 객체를 통해 현재 요청의 정보에 접근할 수 있다.
request 객체는 사용자가 서버에 보낸 HTTP 요청의 모든 데이터를 포함하고 있으며 여기에는 URL, HTTP 헤더, 쿼리 매개변수, 쿠키 등이 포함된다.
쿠키에 접근하기 위해서는 request.cookies 속성을 사용한다.
이 속성은 서버로 전송된 쿠키들을 담고 있는 딕셔너리 객체이다. (키(Key)를 사용하여 쿠키의 값 조회)
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/get_cookie')
def get_cookie():
username = requst.cookies.get('username', '게스트')
return f'쿠키로부터 얻은 사용자 이름: {username}'
위의 두 코드 조각을 플라스크 애플리케이션에 합친다.
from flask import Flask, make_response, request, abort
app = Flask(__name__)
@app.route('/set_cookie')
def set_cookie():
resp = make_response('쿠키를 설정합니다')
resp.set_cookie('username', 'John')
return resp
@app.route('/get_cookie')
def get_cookie():
username = requst.cookies.get('username', '게스트')
return f'쿠키로부터 얻은 사용자 이름: {username}'
# 쿠키가 설정된 사용자만 접근 가능한 라우트
@app.route('/secret')
def secret():
username = request.cookies.get('username')
if not username:
#쿠키가 없다면 접근 금지 메시지 반환
abort(403, description="접근 권한이 없습니다. 먼저 쿠키를 설정해 주세요.")
return f'환영합니다. {username}님! 비밀 페이지에 접속하셨습니다.'
해당 주소에서 쿠키를 설정하고 http://127.0.0.1:5000/secret 경로로 이동하면 설정된 쿠키를 기반으로 비밀 페이지에 접근할 수 있다. 만약 cookie를 설정하지 않고 해당 경로로 이동하면 접근 권한이 없다는 메시지가 표시될 것이다.
추가로, 응답 객체를 resp 라고 가정했을 때 쿠키를 삭제하려면 resp.delete_cookie('cookie_name') 메서드를 사용한다.
@app.route('/delect_cookie')
def delete_cookie():
resp = make_response('쿠키를 삭제합니다.')
resp.delete_cookie('username')
retrun resp
[쿠키를 설정할 때 사용할 수 있는 다양한 옵션들]
1. max_age 옵션
resp.set_cookie('username', 'John', max_age=60*60*24*7)
max_age 옵션은 쿠키가 유지될 시간을 초 단위로 설정한다.
위 코드에서 'max_age=60*60*24*7'은 쿠키가 생성된 시점부터 7일동안 유효하다는 것을 의미한다.
(시간이 지나면 쿠키는 자동으로 만료되어 브라우저에서 삭제 된다)
2. expires 옵션
resp.set_cookie('username', 'John', expires=datetime.datetome(2027, 11, 7))
expires 옵션은 쿠키가 만료되는 정확한 날짜와 시간을 설정할 수 있다. datetime.datetime 객체를 사용하여 날짜와 시간을 지정할 수 있다. (위 코드는 쿠키가 2027년 11월 7일에 만료되도록 설정.)
3. path 옵션
resp.set_cookie('username', 'John', path='/app')
path 옵션을 통해 쿠키의 유효 경로를 제한할 수 있다. 쿠키는 기본적으로 도메인의 모든 경로에 대해 유효하다.
(위 코드는 '/app' 경로와 이 경로의 하위 경로에 대해서만 쿠키가 유효하다)
4. domain 옵션
resp.set_cookie('username', 'John', domain='example.com')
domain 옵션을 설정하면 쿠키가 특정 도메인에서 유효하게 된다. 이렇게 설정하면 서브 도메인 간에 쿠키를 공유할 수 있다.
(위 코드는 'example.com' 도메인과 그 하위 도메인에서 쿠키를 사용할 수 있게 한다)
5. secure 옵션
resp.set_cookie('username', 'John', secure = True)
secure 옵션이 True로 설정되면, 쿠키는 HTTPS 연결을 통해서만 전송된다. 이는 쿠키가 암호화되어 안전하게 전송되도록 보장한다.
6. httponly 옵션
resp.set_cookie('username', 'John', httponly = True)
httponly 옵션을 True로 설정하면, 쿠키는 웹 서버를 통해서만 접근할 수 있다. 이는 쿠키가 클라이언트 사이드의 스크립트에 의한 공격으로부터 안전하도록 도와준다.
이러한 옵션들을 사용하면 쿠키 관리를 세밀하게 조정할 수 있다.
'[파이썬 Projects] > <파이썬 웹개발>' 카테고리의 다른 글
[파이썬] 플라스크(Flask) - 데이터베이스 (1) (0) | 2024.07.16 |
---|---|
[파이썬] 플라스크(Flask) - 로깅 (0) | 2024.07.16 |
[파이썬] 플라스크(Flask) - 블루프린트 (0) | 2024.07.15 |
[파이썬] 플라스크(Flask) - 정적 파일 (0) | 2024.07.14 |
[파이썬] 플라스크(Flask) - 템플릿 (1) | 2024.07.14 |