必要なもの一覧
app.py
app.pyは、全体のコントロールをするところになりますので、これからも何回か出てきますが、今回はLOGInに関するところだけ記述します。
app = Flask(__name__) bcrypt = Bcrypt(app) app.secret_key = 'thequickbrownfox' app.permanent_session_lifetime = datetime.timedelta(minutes=3) #connect & cursor public con = None cur = None script_directory = os.path.dirname(os.path.abspath(__file__)) def connect(): global mdb global con global cur mdb = PADb() con = mdb.getConnect() cur = mdb.getDictCursor() @app.route("/login", methods = ["POST", "GET"]) def login(): if request.method == "POST": session.permanent = True userid = request.form.get("id") password = request.form.get("password") passByte = bcrypt.generate_password_hash(password=password) passHash = passByte.decode('utf-8') connect() if request.form.get("signin"): # 存在チェック #timeout check users = User(con,cur) try: checkid = users.getUser(userid) except: return render_template("login.html",errmess="タイムアウトしました。再ロードしてください") if userid == checkid.get("uid",0): if bcrypt.check_password_hash(checkid.get("pass"),password): session["id"] = userid return redirect(url_for("top")) else: return render_template("login.html",errmess="idまたはpasswordが違います") else: return render_template("login.html",errmess="idまたはpasswordが違います") elif request.form.get("signup"): # 存在チェック users = User(con,cur) checkid = users.getUser(userid) if checkid != "" and passHash != "": if userid == checkid.get('uid',0): return render_template("login.html",errmess="idがすでに使われています") else: users.newUser(userid,passHash) session["id"] = userid return render_template("signup.html",id=userid) else: return render_template("login.html",errmess="idを指定してください") # login済みであれば入場できる else: if "id" in session: return redirect(url_for("top")) return render_template("login.html")
loginに来た時に、データベースへのコネクトを行います。ただ、しばらく放置した場合、タイムアウトしてしまうので、その時はまたloginに戻るのでその時に再度コネクトします。
アカウントを持たないときはsignupに行きます。
LOGIN画面
つづいてlogin用のhtmlが必要なので作成します。画面の作成はBootstrap5のサンプル画面をそのまま使いました。
<!DOCTYPE html> <html lang="jp"> <head> <meta charset="UTF-8"> <title>Event Photos</title> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css')}}"> </head> <body class="text-center"> <div id="login-form" class="container"> <form class="form-signin" action="/login" method="POST"> <h1 class="h3 mb-3 fw-normal">Event Photos Sign in</h1> <p class="mt-1 mb-1 text-muted"><small>小さな写真を共有するサイトです</small></p> <div class="form-floating"> <input type="text" class="form-control" id="floatingInput" name="id" placeholder="your id" required> <label for="floatingInput">Id</label> </div> <div class="form-floating"> <input type="password" class="form-control" id="floatingPassword" name="password" placeholder="Password" required> <label for="floatingPassword">Password</label> </div> <button class="w-100 btn btn-lg btn-primary" type="submit" name="signin" value="signin">Sign in</button> <button class="w-100 btn btn-lg btn-secondary" type="submit" name="signup" value="singup">Sign Up(初回)</button> <p class="text-danger">{{errmess}}</p> <p class="mt-5 mb-3 text-muted">eternalkagosima © 2022</p> </form> </div> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script> </body> </html>
Bootstrap5の説明は省略します。idとpasswordをformで宣言して、buttonでsubmitします。pythonanywhereにメールでもついていればちゃんと確認メールするのですが、今回はないので無検査となります。初回だけSing Upを押してもらい、次回以降はSign inでログインしてもらいますので、その区別をつけています。
flaskで書いてあります。app.pyとHTMLとのデータの渡しと関係するクラスで書いてあります。
rootアドレスへの参照によってまだここに出てきていないtop()関数に処理が渡ります。で、ログインしているかセッションでチェックして、入ってなければlogin()関数が呼ばれます。
プログラムのいたるところでセッションのチェックで異常があればloginに帰ってきます。
ID,PASSWORDをフォームから受信して、passwordはHASH化しておきます。このメソッドは呼び出すたびにシードを変えているので違う結果を返します。作られたhashの中にシードも入れてあるので、check_password_hashでそれを再現して、同じになるかで確認します。
最初の判別は、signinとsignupです。どちらのボタンを押されたかで変わってきます。
signinならば、データベースからidで検索して、入力されたpasswordとデータベースのpasswordをcheck_password_hashで確認して同じならばセッションを設定してtopに移動します。
signupならば、idに空きがあるかチェックして空いていればデータベースにidとhashを入れて、signup.htmlに移動します。簡単な仕様を表示します。