on
188일차 백엔드 Flask - 정리 1
188일차 백엔드 Flask - 정리 1
//================================
로그인을 할 때, 특별한 사용자임을 알려주기 위해서 특별한 코드를 넣어서, HTTP response(응답)에 넣어서 보내줄 수가 있는데, 이것을 쿠키(Cookie)라고 한다. 그리고 이 쿠키에 SetCookie를 같이 보내서, 다음에 request(요청)할 때는, 이 정보를 같이 보내달라고 전한다.
그리고 세션이 있다. 예를 들어, kwon 이라는 사용자가 로그인을 했으며, 이 정보를 전송한다면.
kwon 데이터와 요청의 기본적인 정보, 서버 정보를 합쳐서 특별한 String을 만든다.
즉, 로그인을 요청 할 경우, 특별한 String을 해석해서 사용자가 맞을 경우, 응답을 한다.
세션은, 요청을 1회성으로 여러 번 하는 것들을, 동일한 사용자가 여러 번 요청 하는 것을 세션이라고 한다.
다만, 이 코드에 실제 정보가 들어가 있는지, 아니면 실제 정보는 서버 안에 있고, 서버 안에 있는 정보를 변환해서 보내주는 지를, 이것으로 쿠키와 세션을 구분할 때는, 이 특별한 String을 세션이라고 부른다.
그래서 세션은 광의(어떤 말의 개념을 정의할 때, 넓은 의미)의 의미가 있고,
세션과 쿠키를 구분할 때, 세션을 지칭할 때 사용한다.
Tip : F12 - Network에서 Preserve log, Disable cache 체크 (css를 바꿔도 표시가 안될수도 있어서)
//================================
session_mgmt(매니지먼트).py
user_email을 가져오는 것은 로그인과 비슷한 일을 하는 것이다. 패스워드만 없을 뿐이지.
로그인이 되면, login_user(user)라는 것으로 로그인을 하고, 그러면 세션을 다음번 부터는 해당 세션 정보로 요청을 하라고 set-cookie해서 보내지고, 그다음부터 요청들은 세션정보를 가지고 요청을 하는 것이고,
그러면 그 세션정보를 기반으로 해서 current_user.is_authenticated를 통해 인증된 유저인지를 User 클래스를 기반으로, 그리고 세션 정보를 기반으로 자동으로 체크해준다. 이 두가지의 기능이 세션 매니지먼트를 하는 것이라고 이해하자.
user = User.create(user_email, blog_id) <- User 클래스
//================================
-blog_abtest.py-
from flask_login import LoginManager, current_user, login_required, login_user, logout_user, fresh_login_required
app = Flask(name, static_url_path='/static')
app.register_blueprint(blog.blog_abtest, url_prefix='/blog')
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.session_protection = "strong"
-blog.py-
login_user(user, remember=True, duration=datetime.timedelta(days=365))
login_user를 하기 전에, 맨 처음에 flask 앱을 실행 할때는, 세션을 관리하기 위해서 flask_login을 선언하고,
LoginManager()이라는 flask_login에 있는 함수를 호출해줘서, login_manager라는 객체를 만들고 넣어준다음에,
그 login_manager 객체 안에, 해당 객체를 넣어야 한다.(flask 객체 = app을 넣으면 된다.)
login_manager.session_protection = "strong"은 세션을 만드는 방법을 더 견고하게 보호하도록 설정한다.
LoginManager() 객체에 있는, login_user를 통해서 해당 객체의 사용자 객체를 추가해야 된다라는 뜻이고, 그러면 세션이 생성이 된다.
그 다음에는, current_user.id와 current_user.is_authenticated를 하면, 사용자가 로그인 됬는지 안됬는지 체크할 수 있다.
특정 API 같은 경우에, 만약 로그인된 사용자만 접근이 가능하도록 설정하고 싶다면, @login_required 데코레이터를 사용해서 해당 API를 호출할 때, 세션 정보를 판단해서, 사용자가 로그인이 안되어 있다면 API를 사용 못하도록 API레벨로도 관리할 수 있다.
문제는 이를 위해서는 사용자 객체를 구현해야 하는 User class 구현 예가 많지 않고, 적절한 예를 찾기가 어렵다.
여기서는 가이드만을 가지고 기본기를 다진다.
User class에는 flask_login 라이브러리의 UserMixin 클래스를 상속받아 구현하는 것만 가이드이다.
Flask 앱을 처음 실행할 때, 최상단에 앱 객체(app = Flask(name, static_url_path='/static')를 만들고, 그 다음에 LoginManager()를 가지고 세션을 관리할 수 있는 객체를 만들고, 여기에다가 이 앱을 넣어주는데,
여기서 세션을 생성을 할 때, 앱만의 시크릿 키(app.secret_key = os.urandom(24))를 사용한다. 그래서 서버를 띄울 때, 특별한 코드를 시크릿 키로 생성하고, 다시 서버를 띄우면 다른 랜덤한 시크릿 키로 바뀐다. 그래서 보안성을 관리하기 위해서 시크릿 키를 사용한다. 하지만, 랜덤하게 시크릿 키를 생성하면, 기존의 flask를 종료하고 다시 키면, 기존의 세션 정보를 다시 사용할 수가 없다.
지금 전송한 세션 정보가 사용자 ID를 확인하기 위해서는 app의 시크릿 키를 사용을 하는데, 이 키가 바뀌면 기존의 세션정보에서 내가 원하는 사용자 정보를 확인 할 수가 없다.
예를 들어, 블로그에 내가 메일주소를 입력하고 구독을 했다면, 그 다음부터 계속 구독중이라고 떠야 하는데, secret key를 랜덤한 값으로 사용하면, 서버를 끄고 다시 켰을 때, 다시 이메일 주소를 입력하고 구독하라고 뜬다.
하지만, 고정적인 값을 시크릿 키로 사용하면 세션 정보가 계속 유지가 된다. 그래서 시나리오에 따라서 설정해준다.
그래서, 그 다음에 실제 로그인을 할 때에, login_user()에 우리가 만든 User class로 생성한 사용자 객체를 넣어주면, 세션이 생성이 된다.
from http://kwonputer.tistory.com/211 by ccl(A) rewrite - 2021-03-20 23:26:30