안 쓰던 블로그
[파이썬 Flask] 로그인, 로그아웃 만들기(session) 본문
쿠키와 세션
쿠키와 세션은 클라이언트와 서버가 주고 받는다
쿠키는 시간이 지나면 소멸하고, 서버 자원을 쓰지 않고 클라이언트쪽에 텍스트 파일 형태로 저장된다
보통 자동 로그인이나 팝업 창의 "오늘 이 창을 더 보지 않기"같은 기능을 위해 사용한다
세션과 관련된 데이터는 서버에 저장되며 서버에서 관리할 수 있다는 점에서 안전성이 좋다
보통 로그인과 같은 보안이 필요한 기능을 쓰고자 하면 세션을 사용한다
플라스크에서는 세션을 key값을 통해 value를 불러오는 딕셔너리 형태로 제공한다
따라서 회원가입을 만들고, 회원가입 때 받아두었던 DB의 id, pw필드와 세션이 일치하는지 확인하는 식으로 로그인 기능을 구현할 수 있다
추가로 로그아웃은 pop이나 remove으로 세션을 제거 하면 된다
먼저 login.html 만든다
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no' />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</head>
<body>
<div class = "container">
<div class="row mt-5">
<h1>로그인</h1>
</div>
<div class="col-12">
<br><br>
<form method="POST">
{{form.csrf_token}}
<div class="form-group">
{{form.userid.label("아이디")}}
{{form.userid(class="form-control", placeholder="아이디")}}
</div>
<div class="form-group">
{{form.password.label("비밀번호")}}
{%if form.password.errors%} <!--로그인이 실패하면-->
{{form.password.errors.0}} <!--첫번째 에러메시지 출력한다-->
{%endif%} <!--실패하지 않았으면 비밀번호 넘긴다-->
{{form.password(class="form-control", placeholder="비밀번호")}}
</div>
<button type="submit" class="btn btn-primary">제출</button>
</form>
</div>
</div>
</body>
</html>
app.py
import os #디렉토리 절대 경로
from flask import Flask
from flask import render_template #template폴더 안에 파일을 쓰겠다
from flask import request #회원정보를 제출할 때 쓰는 request, post요청 처리
from flask import redirect #리다이렉트
#from flask_sqlalchemy import SQLAlchemy
from Models import db
from Models import User
from flask import session #세션
from flask_wtf.csrf import CSRFProtect #csrf
from Forms import RegisterForm, LoginForm
app = Flask(__name__)
@app.route('/')
def mainpage():
userid = session.get('userid',None)
return render_template('main.html', userid=userid)
@app.route('/register', methods=['GET', 'POST']) #GET(정보보기), POST(정보수정) 메서드 허용
def register():
form = RegisterForm()
if form.validate_on_submit(): #유효성 검사. 내용 채우지 않은 항목이 있는지까지 체크
usertable = User()
usertable.userid = form.data.get('userid')
usertable.email = form.data.get('email')
usertable.password = form.data.get('password')
db.session.add(usertable) #DB저장
db.session.commit() #변동사항 반영
return "회원가입 성공"
return render_template('register.html', form=form) #form이 어떤 form인지 명시한다
@app.route('/login', methods=['GET','POST'])
def login():
form = LoginForm() #로그인폼
if form.validate_on_submit(): #유효성 검사
print('{}가 로그인 했습니다'.format(form.data.get('userid')))
session['userid']=form.data.get('userid') #form에서 가져온 userid를 세션에 저장
return redirect('/') #성공하면 main.html로
return render_template('login.html', form=form)
@app.route('/logout', methods=['GET'])
def logout():
session.pop('userid', None)
return redirect('/')
if __name__ == "__main__":
#데이터베이스---------
basedir = os.path.abspath(os.path.dirname(__file__)) #현재 파일이 있는 디렉토리 절대 경로
dbfile = os.path.join(basedir, 'db.sqlite') #데이터베이스 파일을 만든다
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + dbfile
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True #사용자에게 정보 전달완료하면 teadown. 그 때마다 커밋=DB반영
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #추가 메모리를 사용하므로 꺼둔다
app.config['SECRET_KEY']='asdfasdfasdfqwerty' #해시값은 임의로 적음
csrf = CSRFProtect()
csrf.init_app(app)
db.init_app(app) #app설정값 초기화
db.app = app #Models.py에서 db를 가져와서 db.app에 app을 명시적으로 넣는다
db.create_all() #DB생성
app.run(host="127.0.0.1", port=5000, debug=True)
/login 과 /logout을 추가한다
로그인은 세션에 userid를 등록하는 식이고, 로그아웃은 세션에서 userid를 삭제한다
session변수에 값을 저장하면 알아서 클라 정보를 구분해 줘서 편리하다
메인 페이지에다가 세션에서 userid이름을 가져오는 부분을 추가한다
userid정보는 main.html에다가 전달하여 로그인 성공 시 표시될 것이다
Forms.py
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms import PasswordField
from wtforms.validators import DataRequired, EqualTo
from Models import User #Models.py 가져옴
class RegisterForm(FlaskForm):
userid = StringField('userid', validators=[DataRequired()])
email = StringField('email', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired(), EqualTo('password_2')]) #비밀번호 확인
password_2 = PasswordField('password_2', validators=[DataRequired()])
class LoginForm(FlaskForm):
class UserPassword(object):
def __init__(self, message=None):
self.message = message
def __call__(self, form, field):
userid = form['userid'].data
password = field.data
usertable = User.query.filter_by(userid=userid).first()
if usertable.password != password:
raise ValueError('비밀번호 틀림')
userid = StringField('userid', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired(), UserPassword()])
wtf패키지를 이용한 form을 생성해서 유효성을 검사한다
main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no' />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</head>
<body>
<div class = "container">
<div class="row mt-5">
<h1>이곳은 메인 페이지</h1>
</div>
<br>
<div class=form-group>
{%if userid%}
{{userid}}<a>님 안녕하세요!</a><br>
<a href="/logout">로그아웃</a>
{%endif%}
</div>
</div>
</body>
</html>
app.py에서 넘어온 userid가 있다면 userid 님 안녕하세요! 를 출력한다
/logout을 연결해 준다
이제 실행하고 /login으로 이동
틀리면 틀렸다고 뜬다
맞으면 메인화면으로 온다
로그아웃을 하면 로그인했던 정보가 사라진다
'언어 > 파이썬' 카테고리의 다른 글
[파이썬] 소켓 프로그래밍-파일 전송, 파일 수신 (11) | 2020.09.07 |
---|---|
[파이썬] 소켓 프로그래밍-1대1 채팅 시스템 (0) | 2020.09.06 |
[파이썬 Flask] 회원가입 웹 시스템 만들기_2 WTF 적용하기 (1) | 2020.09.04 |
[파이썬 Flask] 회원가입 웹 시스템 만들기 (0) | 2020.09.03 |
[Flask] Flask-SQLAlchemy (0) | 2020.09.03 |