- 작성시간 : 2015/09/11 17:55
- 퍼머링크 : mcchae.egloos.com/11184587
- 덧글수 : 5
플래스크에서 세션 정보는 브라우저의 쿠키를 이용합니다.







해당 정보를 플래스크의 세션객체에 넣고 이용하는데
별도의 레디스 서버를 이용합니다.
레디스가 특별히 좋은 이유는 자동으로 파기 조건을 줄 수 있기 때문입니다.
혹시나 비정상 종료로 사용자가 브라우저를 종료하고 나갔다고 하더라도
해당 레디스에서는 자동으로 해당 세션정보를 시간이 지나면 파기합니다.
우선 아래의 코드와 같습니다.
from uuid import uuid4
from datetime import datetime, timedelta
from flask.sessions import SessionInterface, SessionMixin
from werkzeug.datastructures import CallbackDict
from flask import Flask, session, url_for, redirect
import redis
import cPickle
#########################################################################################
# This is a session object. It is nothing more than a dict with some extra methods
class RedisSession(CallbackDict, SessionMixin):
def __init__(self, initial=None, sid=None):
CallbackDict.__init__(self, initial)
self.sid = sid
self.modified = False
#########################################################################################
# Session interface is responsible for handling logic related to sessions
# i.e. storing, saving, etc
class RedisSessionInterface(SessionInterface):
#====================================================================================
# Init connection
def __init__(self, host='localhost', port=6379, db=0, timeout=3600):
self.store = redis.StrictRedis(host=host, port=port, db=db)
self.timeout = timeout
#====================================================================================
def open_session(self, app, request):
# Get session id from the cookie
sid = request.cookies.get(app.session_cookie_name)
# If id is given (session was created)
if sid:
# Try to load a session from Redisdb
stored_session = None
ssstr = self.store.get(sid)
if ssstr:
stored_session = cPickle.loads(ssstr)
if stored_session:
# Check if the session isn't expired
if stored_session.get('expiration') > datetime.utcnow():
return RedisSession(initial=stored_session['data'],
sid=stored_session['sid'])
# If there was no session or it was expired...
# Generate a random id and create an empty session
sid = str(uuid4())
return RedisSession(sid=sid)
#====================================================================================
def save_session(self, app, session, response):
domain = self.get_cookie_domain(app)
# We're requested to delete the session
if not session:
response.delete_cookie(app.session_cookie_name, domain=domain)
return
# Refresh the session expiration time
# First, use get_expiration_time from SessionInterface
# If it fails, add 1 hour to current time
if self.get_expiration_time(app, session):
expiration = self.get_expiration_time(app, session)
else:
expiration = datetime.utcnow() + timedelta(hours=1)
# Update the Redis document, where sid equals to session.sid
ssd = {
'sid': session.sid,
'data': session,
'expiration': expiration
}
ssstr = cPickle.dumps(ssd)
self.store.setex(session.sid, self.timeout, ssstr)
# Refresh the cookie
response.set_cookie(app.session_cookie_name, session.sid,
expires=self.get_expiration_time(app, session),
httponly=True, domain=domain)
#########################################################################################
# Create an application
app = Flask(__name__)
app.session_interface = RedisSessionInterface()
#########################################################################################
@app.route("/")
def index():
session.permanent = False
if not 'refreshed'in session:
session['refreshed'] = 0
text = "You refreshed the page %d times" % ( session['refreshed'] )
text += '<br/><a href="/kill">Reset</a>'
text += '<br/>dbname="%s"' % session.get('dbname','NULL')
session['refreshed'] = session['refreshed'] + 1
return text
#########################################################################################
@app.route("/dbset/<dbname>")
def dbset(dbname):
session['dbname']=dbname
return redirect(url_for('index'))
#########################################################################################
@app.route("/kill")
def kill():
session.clear()
return redirect(url_for('index'))
app.debug = True
#########################################################################################
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
위의 코드를 redissess.py 라는 파일로 저장합니다.
물론 우분투 시스템에서 필요한 패키지를 설치하고,
$ sudo apt-get install redis-server
$ sudo pip install flask
$ sudo pip install redis
$ sudo python redissess.py
라고 실행시키면...
* Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
* Restarting with stat
와 같이 화면에 해당 서비스가 돌고 있다고 나오고,
다른 시스템에서 브라우저를 띄워,
http://{해당주소}:8080
로 접속을 하면

위와 같이 나옵니다.
화면을 Refresh 시키면,

위와 같이 동일 세션이기 때문에 page 카운트가 증가합니다.

dbset 이라는 redirect 명령으로 foodb 라고 dbset() 함수를 돌리면,

위와 같이 다른 탭에서도 동일한 세션 정보가 먹어 앞서 설정한 dbname이 foodb라고 나오는 군요...
동일한 브라우저의 다른 창을 띄워서 해보아도 동일한 세션으로 인식하는 군요.
그러나 다른 브라우저에서 새로 띄우면,

새로운 세션으로 인식합니다.

다른 bardb 라고 dbset()을 시키면,

해당 bardb 라는 이름이 그 해당 브라우저에서는 동일하게 가지고 있게 됩니다.
이렇게 하여 세션 정보를 gnuicorn 등의 몇 개의 인스턴스를 돌리던지 상관없이
세션을 하나로 관리할 수 있게 되겠군요.
어느 분께는 도움이 되셨기를 바랍니다...
덧글
따로 데이터베이스를 사용하지 않아서 좋아요~!