내일배움단 11일메이킹챌린지 12일차

python flask 로그인 기능 구현

우리는 우선 로그인기능을 구현하지 않고 쇼핑몰페이지를 만들었었는데, 어제 발표를 듣다보니 로그인 기능을 구현한 곳이 있었다. 로그인(회원가입)하지 않고 주문하는 것의 간편함도 있어서 나쁘지 않지만, 그래도 대부분의 쇼핑몰(올버즈allbirds 코리아 처럼 아닌 곳도 있지만)이 회원가입-로그인 시스템을 만들어두는 데에는 이유가 있다.
우선 처음의 번거로움(회원가입 - 이것도 요즘은 간편로그인이 많아서~)만 지나고 나면 연락처, 주소 등등을 매번 새로 입력하지 않아도 기본정보로 불러올 수 있다는 점, 그리고 광고메시지를 보내거나 개인아이디에 포인트, 쿠폰 등을 제공해 구매유도를 할 수 있다는 점 등 그냥 잠깐 떠올려봐도 꽤 많은 이점을 가질 수 있다.

그리고 웹 프레임워크인 flask로 로그인 기능을 구현해보고 싶었다. DB에 정보를 암호화해서 넣는 것도, mongoDB에서 어떻게 하는지 궁금했다.

flask로 로그인 구현하기 예제
https://youngminieo1005.tistory.com/92
https://niceman.tistory.com/191

flask, pymongo로 로그인 구현하기 예제
https://scribblinganything.tistory.com/196

flask, pymongo 패스워드 암호화 관련 포스팅
https://scribblinganything.tistory.com/197

파이썬 플라스크 소스코드

from flask import Flask, render_template, jsonify, request, session, url_for, redirect, flash
from flask_pymongo import PyMongo
from werkzeug.security import generate_password_hash, check_password_hash

# Create application
app = Flask(__name__)

app.config["MONGO_URI"] = "mongodb://localhost:27017/bdd"
mongo = PyMongo(app)
app.secret_key = 'supersupersecret'

# 세션에 logged_in값이 true면 로그인 상태
@app.route('/')
def main():
    if session.get('logged_in'):
        return render_template('loggedin.html')
    else:
        return render_template('index.html')
        
# session["logged_in"] = True 를 넣어주면 로그인 성공한 이후의 상황이 됨.
@app.route('/login', methods=['GET', 'POST'])
def member_login():
    if request.method == 'GET':
        return render_template('index.html')
    elif request.method == 'POST':
        userid = request.form.get("userid", type=str)
        pw = request.form.get("userPW", type=str)

        if userid == "":
            flash("아이디를 입력하세요")
            return render_template('index.html')
        elif pw == "":
            flash("비밀번호를 입력하세요")
            return render_template('index.html')
        else:
            users = mongo.db.users
            id_check = users.find_one({"userid": userid})
            #print(id_check["pw"])
            #print(generate_password_hash(pw))
            if id_check is None:
                flash("아이디가 존재하지 않습니다.")
                return render_template('index.html')
            elif check_password_hash(id_check["pw"],pw):
                session["logged_in"] = True
                session["now_login_id"] = id_check["userid"]
                print(session)
                return render_template('loggedin.html')
            else:
                flash("비밀번호가 틀렸습니다.")
                return render_template('index.html')

@app.route("/logout", methods=["POST"])
def logout():
    session['logged_in'] = False
    return render_template('index.html')

@app.route("/join", methods=["GET", "POST"])
def member_join():
    if request.method == "POST":
        userid = request.form.get("userid", type=str)
        pw = request.form.get("userPW", type=str)
        name = request.form.get("name", type=str)
        phone = request.form.get("phone1", type=str)+"-"+request.form.get("phone2", type=str)+"-"+request.form.get("phone3", type=str)
        postcode = request.form.get("postcode", type=str)
        addr = request.form.get("addr", type=str)
        extraAddr = request.form.get("addr_remain", type=str)

        if userid == "":
            flash("ID를 입력해주세요")
            return render_template("join.html")
        elif pw == "":
            flash("패스워드를 입력해주세요")
            return render_template("join.html")

        users = mongo.db.users
        check_cnt = users.find({"userid": userid}).count()
        if check_cnt > 0:
            flash("이미 존재하는 아이디입니다.")
            return render_template("join.html")

        to_db = {
            "userid": userid,
            "pw": generate_password_hash(pw),
            "name": name,
            "phone": phone,
            "postcode": postcode,
            "address": addr,
            "extraAddress": extraAddr,
        }
        users.insert_one(to_db)
        last_signup = users.find().sort("_id", -1).limit(5)
        for _ in last_signup:
            print(_)

        flash("가입이 완료되었습니다. 감사합니다!")
        return render_template("index.html")
    else:
        return render_template("join.html")
        

HTML 소스코드

<!-- index.html -->
<div>
  <form action = "/login" method="POST">
    ID: <input type="text" name="userid"/>
    PASSWORD: <input type="password" name="userPW">
    <button type="submit" class="btn btn-info">로그인</button>
    <a href="/join"><button type="button" class="btn btn-info">회원가입</button></a>
  </form>

</div>



<!-- loggedin.html -->
<form action="/logout" method="post">
  <button type="submit" class="btn btn-info">로그아웃</button>
</form>



<!-- join.html -->
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
            integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
            crossorigin="anonymous"></script>
    <link rel="stylesheet" type="text/css" href="../static/css/common.css">
    <!-- 다운로드받지 마시고 CDN 이용하듯 이대로 링크하세요. API 의 버그 수정 등의 변화를 일일히 적용할 필요가 없습니다. ssl 대응되므로 url 을 수정하지 마세요. -->
    <script src="https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
    <script src="https://xeno.work/roadzip/daum.js"></script>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
          crossorigin="anonymous">
    <title></title>
</head>
<body>
<form action="" method="post" id="joinform">
  <div class="input-group mb-3">
    ID : <input type="text" class="form-control" name="userid" />
  </div>
  <div class="input-group mb-3">
    PW : <input type="password" class="form-control" name="userPW" id="pw" onchange="isSame()" />
  </div>
  <div class="input-group mb-3">PW(check) :
    <input type="password" class="form-control" name="confirmPW" id="pwCheck" onchange="isSame()" /> <span id="same"></span>
  </div>
  <div class="input-group mb-3">
    이름 : <input type="text" class="form-control" name="name" />
  </div>
  <div class="input-group mb-3">
    <select class="custom-select" name="phone1" id="phone1">
      <option value="010" selected>010</option>
      <option value="011">011</option>
      <option value="016">016</option>
      <option value="017">017</option>
      <option value="018">018</option>
      <option value="019">019</option>
    </select>
    -
    <input type='tel' class="form-control" name="phone2" id="phone2" maxlength="4">
    -
    <input type='tel' class="form-control" name="phone3" id="phone3" maxlength="4">
  </div>
  <!--우편번호 찾기 API -->
  <form>
    <div class="input-group mb-3">
      <input class="form-control" type="text" id="postcode" name="zipcode" placeholder="우편번호">
      <button type="button" class="btn btn-info DaumZipFinder">우편번호찾기</button>
    </div>
    <div class="input-group mb-3">
      <input class="form-control" type="text" id="address" name="addr" placeholder="주소">
    </div>
    <div class="input-group mb-3">
      <input class="form-control" type="text" id="extraAddress" name="addr_remain" placeholder="상세주소">
    </div>
  </form>
  <!--우편번호 찾기 API 끝 -->
  <button type="submit" class="btn btn-info" form="joinform">회원가입하기</button>
</form>
<!-- form 아래쪽에 적용하면 되고, head 에 넣을경우 $(function() {}); 로 감싸세요. -->
<script>
    $('button.DaumZipFinder').each(DaumZipFinder);
</script>
</body>

jinja2 문법

userid = something
render_templates(index.html,
		id = userid
        	)

#위와 같이 보낸 후, HTML에서
{{ id }}
#와 같이 쓰면 파이썬 소스코드의 변수 userid에 들어있는 값을 HTML에서 바로 보여줄 수 있다.

{% if id %}
#위와 같은 코드를 이용해 HTML 문서 중간에서 if문도 사용할 수 있다!

https://niceman.tistory.com/151

좋은 웹페이지 즐겨찾기