포스트

[Flask] 회원 기능 구현하기 <1 : 로그인 구현하기>

0. 읽기 전에…

이전 Cookie & Session 링크

이 글을 읽기 전에 위 링크를 통해 공부했던것을 보고 오면 왜 session을 이용하는지 알 수 있다.

1. 공식 문서 읽어보기

session에 대해 flask에서 제공하는 공식 문서가 있다길래 찾아보았다.

Quickstart — Flask Documentation (1.1.x)

설명하는 내용은 이전 쿠키 & 세션 링크에 정리해둔 내용과 같다

여기서 제공하는 코드를 조금 변경해보자

이번 글에서 내가 해볼 것들은…

  1. 로그인 & 로그아웃 구현
  2. 로그인 했을 경우엔 로그아웃 버튼만 표시
  3. 로그인 했을 경우엔 메인 페이지에서 아이디 표시하기
  4. 로그아웃 했을 경우엔 로그인 버튼만 표시
  5. 로그인 지속시간 설정

이것들에 대해서 구현해볼 계획이다.

아래는 session에 대해 공식에서 제공하는 코드이다. 주석은 내가 따로 달았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from flask import Flask, session, redirect, url_for, request
from markupsafe import escape # HTML에서 마크업 문자열을 안전하게 가져와주는 라이브러리

app = Flask(__name__)

# 시크릿 키는 완전 랜덤하게 생성해야함.
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    if 'username' in session: # 만약 세션에 username이 존재한다면...
        return 'Logged in as %s' % escape(session['username']) # username을 표시
    return 'You are not logged in' # 세션에 username이 없다면 로그인 페이지로

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username'] # 세션에 'username'을 request.form의 'username'으로 설정
        return redirect(url_for('index')) # index 함수로 이동(이곳에선 홈 경로)
    return ''' 
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    ''' # request.method가 POST가 아닌 경우엔 로그인 form으로 이동

@app.route('/logout')
def logout():
    # 간단하게 pop하면 세션이 없어지면서 로그아웃된다.
    session.pop('username', None)
    return redirect(url_for('index')) # 로그아웃하면 홈으로

2. 수정하기

공식 문서 코드가 쉬워서 좋았지만 내가 원하는 기능이랑 다른 부분은 많았다.

  1. 공식 문서에선 입력한 username을 바로 띄워주지만 나는 회원 정보가 따로 있고 회원 아이디와 패스워드를 조회하게 만들고 싶다.
  2. username을 변수로 넘겨줘야 한다.
  3. 입력한 로그인 데이터가 없다면, 없다는 메시지를 띄워준다.

2.0 기본

1
2
3
4
5
6
7
8
9
from flask import Flask, url_for, request, session, redirect, render_template
from markupsafe import escape
from datetime import timedelta
from Model import user # 테스트용으로 만든 회원 데이터

app = Flask(__name__)
app.secret_key = "hihigoddffdkfjeiriir" # 복잡하게 만들어야됨

app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=30) # 로그인 지속시간 30분

app.config 에 대한 정보는 해당 링크에서 확인할 수 있다.

https://flask-docs-kr.readthedocs.io/ko/latest/config.html

회원 데이터는 다음과 같이 작성했다.

1
2
3
4
5
6
7
users = [
    {"id" : "admin", "password" : "1234"},
    {"id" : "kim", "password" : "0000"},
    {"id" : "lee", "password" : "2345"},
    {"id" : "park", "password" : "3333"},
    {"id" : "son", "password" : "34jj"},
        ]

2.1 index():

1
2
3
4
5
6
@app.route('/')
def index():
    if 'username' in session: # 세션에 username이 있다면...
        return render_template('home.html',userid = escape(session['username']))
    
    return render_template('home.html') # 로그인 안한 상태

크게 달라진 부분은 없다. render_template를 사용해 userid를 변수로 해서 넘겨주었다.

home.html 은 다음과 같이 구성했다.

1
2
3
4
5
6
7
8
9
10
11
12
<html>
   <body>
      
         {% if not userid %}
            <button type="button" class="login-button" onclick="location.href='/login'">Login</button>
         {% else %}
            <button type="button" class="logout-button" onclick="location.href='/logout'">Logout</button>
            <h1>Welcome, {{ userid }}!</h1>
         {% endif %}
      
   </body>
</html>

userid가 존재하지 않는다면 로그인 버튼을, 존재한다면 로그아웃 버튼과 userid를 출력했다.

2.2 login():

로그인 버튼을 눌렀을 시, 실행되는 페이지이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@app.route('/login', methods = ['GET','POST'])
def login():
    if request.method == 'POST':
        entered_id = request.form['userid'] # 사용자가 입력한 id
        entered_pw = request.form['userpw'] # 사용자가 입력한 pw

        found_user = None
        for userdata in user.users:
            if (entered_id == userdata['id'] and entered_pw == userdata['password']):
                session['username'] = entered_id
                session['userpw'] = entered_pw
                found_user = entered_id
                break
    
        if found_user:
            return redirect(url_for('index'))
        else: 
            return render_template('login.html',message = "회원 정보가 없습니다.")
            
    return render_template('login.html')

사용자가 입력한 아디이와 비밀번호를 바로 session에 저장하지 않는게 포인트다.

바로 저장했을시엔 로그인에 성공하든 실패하든 session에 아이디가 저장되어 if 'username' in sessionTrue 가 되어버린다! 그러면 뒤로가기를 했을 시 잘못된 아이디를 표시하게 된다.

먼저 entered_id 라는 변수를 따로 할당해, 데이터베이스에 존재할 경우 session에 저장해주었다.

회원 정보에 존재하는 아이디, 비밀번호를 입력했다면 홈페이지로 돌아가 회원 아이디를 출력해준다.

잘못된 아이디를 입력한다면 로그인 페이지에 그대로 남아있고, 회원 정보가 없습니다. 라는 메시지를 띄워준다.

login.html은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
   <body>
   
      <form action = "" method = "POST">
         <p>I D : <input type = "text" name = "userid" /></p>

         <p>P W : <input type = "text" name = "userpw" /></p>

         <p><input type = "submit" value = "submit" /></p>

         
      </form>
      
   </body>
</html>

메시지가 존재할 경우에만 메시지를 띄워주도록 했다.

로그아웃에 변경점은 없다.

3. 결과

바로 로컬 서버에서 확인해보자.

바로 실행했을땐 세션에 아무 정보가 없기 때문에 logout 버튼은 나오지 않고 로그인 버튼만 나오게 했다.

적절한 아이디를 입력해보자

적절한 아이디라면, 홈페이지로 돌아와 아이디를 띄워준다.(+ 로그아웃 버튼)

만약 적절하지 못한 아이디라면 메시지를 띄워준다. 이때 뒤로 돌아간다 하더라도 아이디를 띄워주지는 않는다.

4. 추후 미션

지금은 간단한 테스트를 해보기 위해 간이 데이터베이스를 만들어 실험해보았지만 다음엔 데이터베이스에 대한 적절한 공부를 한 후 회원가입, 회원탈퇴 기능도 만들어보겠다.



이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.