SW/Python

[Flask] 로그인 기능

17Hyuk 2022. 5. 3. 01:05

로그인을 구현하기 위해서는 session이 필요하다.

기술적인 부분은 내가 잘 모르기 때문에 다른 블로그를 참조하길 바란다.

 

기본적으로 template를 사용하므로 파일은 이런식으로 했다.

 

 

app.py

from flask import Flask, render_template, request, redirect, session
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Length
import app_sql


# StringField : <input type="text">
# PasswordField : <input type="password">
# DataRequired : 유효성검사

app = Flask(__name__)
app.secret_key = "ssijfo@#!@#123"       #session을 사용하기 위해서는 반드시 있어야함

class loginform(FlaskForm):
    #이 변수명이 input의 name과 id가 되는거임 <input id="user_id" name="user_id" type="text" value="">
    #validators=[DataRequired()] : 필수 입력하도록 하는 함수
    user_id = StringField('라벨1',validators=[DataRequired(), Length(max=10)])
    user_pw = PasswordField('라벨2',validators=[DataRequired(), Length(max=10)])

@app.route('/')
def index():
    app_form = loginform()      # 클래스를 할당
    if 'user_id' in session:
        return render_template(
            'index.html',
            html_form = app_form,
            html_login = True,
            html_name = session.get('user_id'),
            html_title = '로그인성공')
    else:
        return render_template('index.html',
        html_form = app_form,
        html_login = False,
        html_title = '로그인대기')


#session은 딕셔너리임
#request.args는 GET에서 사용
#request.form은 POST에서 사용

@app.route('/login/', methods=['post'])
def login():
    form_id = request.form['user_id']
    form_pw = request.form['user_pw']
    login_state = app_sql.login(form_id, form_pw)   #로그인 실패시 None 성공시 값이 있음
    if login_state != None:
        session['user_id'] = form_id       
    return redirect('/')

@app.route('/register/', methods=['post'])
def register():
    form_id = request.form['user_id']
    form_pw = request.form['user_pw']
    app_sql.register(form_id, form_pw)    
    return redirect('/')


@app.route('/logout/', methods=['post'])
def logout():
    session.pop('user_id')      # session에서 제거
    return redirect('/')

app.run(host='0.0.0.0', port=5000, debug=True)

 

app_sql.py

import pymysql

#MySQL 접속
mydb = pymysql.connect(
    user='tmp',
    database='tmpdb',
    passwd='1234',
    host='localhost',
    charset='utf8'
)

#커서생성
sql_cursor = mydb.cursor(pymysql.cursors.DictCursor)


def login(user_id, user_pw):
    command = f'''
    SELECT * FROM login WHERE userid = '{user_id}' AND userpw = '{user_pw}';
    '''
    sql_cursor.execute(command)
    return sql_cursor.fetchone()        # 데이터가 있으며 {'userid': 'A', 'userpw': '1234'}, 없으면 None return

def register(user_id, user_pw):
    command = f'''
    INSERT INTO login VALUES ('{user_id}', '{user_pw}')
    '''
    try:
        sql_cursor.execute(command)         # 중복인 경우 에러 발생하므로 try/except 사용
    except:
        return print('이미 존재하는 회원')
    mydb.commit()
    return print('회원가입 완료')

 

frame.html

<!DOCTYPE html>
<html>
    <head>
        <title>
            {% block title %}
            {% endblock %}
        </title>
        <meta charset="utf-8">
    </head>
    <body>
        <header>
            <h1><a href="/">홈</a></h1>
        </header>
        <nav>
        </nav>
        <article>
            {% block content %}
            {% endblock %}
        </article>
    </body>
</html>

 

index.html

{% extends 'frame.html' %}

<!--제목-->
{% block title %}
    {{html_title}}
{% endblock %}

<!--내용-->
{% block content %}

{% if html_login == True %}
    <h2> {{html_name}} 님 반가워요</h2>
    <form method="post">
        <input type="submit" value="로그아웃" formaction="/logout/">
    </form>
{% else %}
    <h2>로그인</h2>
    <form method="post">
        {{ html_form.user_id.label }}
        {{ html_form.user_id }}
        {{ html_form.user_pw.label }}
        {{ html_form.user_pw }}
        <input type="submit" value="로그인" formaction="/login/">
        <input type="submit" value="회원가입" formaction="/register/">
    </form>
{% endif %}


{% endblock %}

 

 

설명

validators=[DataRequired(), Length(max=10)]

가 있으므로 아래 사진처럼 값이 없으면 경고창이 뜬다.

그리고 글자수는 최대 10개로 제한된다.

@app.route('/login/', methods=['post'])
def login():
    form_id = request.form['user_id']
    form_pw = request.form['user_pw']
    login_state = app_sql.login(form_id, form_pw)   #로그인 실패시 None 성공시 값이 있음
    if login_state != None:
        session['user_id'] = form_id       
    return redirect('/')

로그인 대기

을 보면 form을 통해서 user_id와 user_pw를 가져오는데

def login(user_id, user_pw):
    command = f'''
    SELECT * FROM login WHERE userid = '{user_id}' AND userpw = '{user_pw}';
    '''
    sql_cursor.execute(command)
    return sql_cursor.fetchone()        # 데이터가 있으며 {'userid': 'A', 'userpw': '1234'}, 없으면 None 이 return됨

그 값을 app_sql.py의 log함수 대응을 해서 성공하면 데이터가 있고 실패하면 None이 return된다.

그후 redirect를 통해서 홈으로 가게 된다.

 

회원가입도 유사하나

try/except 를 사용해서 id 중복이 나는 경우 오류 발생을 해결해줬다.

 

 

@app.route('/')
def index():
    app_form = loginform()      # 클래스를 할당
    if 'user_id' in session:
        return render_template(
            'index.html',
            html_form = app_form,
            html_login = True,
            html_name = session.get('user_id'),
            html_title = '로그인성공')
    else:
        return render_template('index.html',
        html_form = app_form,
        html_login = False,
        html_title = '로그인대기')

홈으로 가게 되면

로그인을 성공하게 됐으므로 session 딕셔너리에 'user_id'가 존재하게 되므로 if문이 실행된다.

 

{% if html_login == True %}
    <h2> {{html_name}} 님 반가워요</h2>
    <form method="post">
        <input type="submit" value="로그아웃" formaction="/logout/">
    </form>
{% else %}
    <h2>로그인</h2>
    <form method="post">
        {{ html_form.user_id.label }}
        {{ html_form.user_id }}
        {{ html_form.user_pw.label }}
        {{ html_form.user_pw }}
        <input type="submit" value="로그인" formaction="/login/">
        <input type="submit" value="회원가입" formaction="/register/">
    </form>
{% endif %}

이젠 html_login이 True이므로

로그인 성공

이런 페이지가 출력된다.