はじめに
大晦日の1日だけでゲームを作ってQiitaに記事を投稿できるかチャレンジ。
大晦日といえば、108つのアレですよね。
そうです。煩悩 です。
ということで(?)煩悩をぶっ壊す便利ツール「煩悩デストラクター」を作りました!!!
こちらから遊ぶことができます。遊んでみてね。
http://delphy8.s324.xrea.com/index.html
@Kumanoku と @Delphyilia の合作になります!
早速ゲームを作っていきます!と言いたいところですが、【前編】ではログイン機能を作ります。
ゲーム部分の記事を読みたい!という方は @Delphyilia の【後編】をこちらからどうぞ↓
ログイン機能の実装(Kumanoku担当)
概要
PythonのCGIを使用して、ログイン(ユーザー登録とユーザー認証)の機能を実装します。
以下の2つのCGIを作成します。
- ユーザー登録用CGI(register.cgi)
- ユーザー名とパスワードの入力フォーム
- パスワードをSHA256でハッシュ化
- ユーザー名とハッシュ化パスワードをcsvに保存
- ユーザー認証用CGI(login.cgi)
- ユーザー名とパスワードの入力フォーム
- パスワードをSHA256でハッシュ化
- csvに保存されたユーザー名・パスワードと照合
環境
PythonのCGIが動作するWebサーバーを用意します。今回は無料のレンタルサーバーであるXREAを利用します。
XREAのPythonの実行パスは/usr/bin/python3.6です。詳しいサーバー仕様は以下のXREAのページを参照してください。
ユーザー登録用CGI
#!/usr/bin/python3.6
import cgi
import hashlib
import csv
import os
DATA_FILE = "users.csv"
# ハッシュ化関数
def hash_password(password):
return hashlib.sha256(password.encode()).hexdigest()
# 既存のユーザー名か?
def user_exists(username):
if not os.path.exists(DATA_FILE):
return False
with open(DATA_FILE, "r") as f:
reader = csv.reader(f)
for row in reader:
if row[0] == username:
return True
return False
# csvに保存
def register_user(username, password):
hashed_password = hash_password(password)
with open(DATA_FILE, "a", newline="") as f:
writer = csv.writer(f)
writer.writerow([username, hashed_password])
# ヘッダーの設定
print("Content-Type: text/html; charset=utf-8\n\n")
form = cgi.FieldStorage()
username = form.getvalue("username")
password = form.getvalue("password")
confirm_password = form.getvalue("confirm_password")
if username and password and confirm_password:
if password != confirm_password:
message = "パスワードが一致しません。"
elif user_exists(username):
message = "このユーザー名は既に登録されています。"
else:
register_user(username, password)
message = "登録が完了しました。ログインページに戻ってログインしてください。"
else:
message = "すべてのフィールドを入力してください。"
print(f"""
<html>
<head><title>ユーザー登録</title></head>
<body>
<h1>ユーザー登録</h1>
<form method="post" action="register.cgi">
<label for="username">ユーザー名: </label><input type="text" id="username" name="username" required><br>
<label for="password">パスワード: </label><input type="password" id="password" name="password" required><br>
パスワード確認: <input type="password" name="confirm_password" required><br>
<input type="submit" value="登録">
</form>
<p>{message}</p>
<p><a href="login.cgi">ログインページに戻る</a></p>
</body>
</html>
""")
ユーザー名が被らないように、入力されたユーザー名がcsvに既存であれば弾くようにしています。
実行すると以下のような表示になります。
すべてのフィールドを入力して「登録」を押すと...
登録できました。
ユーザー認証用CGI
#!/usr/bin/python3.6
import cgi
import hashlib
import csv
import os
DATA_FILE = "users.csv"
# ハッシュ化関数
def hash_password(password):
return hashlib.sha256(password.encode()).hexdigest()
# ユーザ認証関数
def authenticate_user(username, password):
hashed_password = hash_password(password)
if not os.path.exists(DATA_FILE):
return False
with open(DATA_FILE, "r") as f:
reader = csv.reader(f)
for row in reader:
if row[0] == username and row[1] == hashed_password:
return True
return False
# ヘッダーの設定
print("Content-Type: text/html; charset=utf-8\n\n")
form = cgi.FieldStorage()
username = form.getvalue("username")
password = form.getvalue("password")
if username and password:
if authenticate_user(username, password):
message = "ログイン成功!"
else:
message = "ユーザ名またはパスワードが間違っています。"
else:
message = "ユーザ名とパスワードを入力してください"
print(f"""
<html lang="ja">
<head><title>ログイン</title></head>
<body>
<h1>ログイン</h1>
<form method="post" action="login.cgi">
<label for="username">ユーザー名: </label><input type="text" id="username" name="username" required><br>
<label for="password">パスワード: </label><input type="password" id="password" name="password" required><br>
<input type="submit" value="ログイン">
</form>
<p>{message}</p>
<p><a href="register.cgi">新規登録はこちら</a></p>
</body>
</html>
""")
実行すると以下のような表示になります。
先ほど登録した内容を入力して「ログイン」を押すと...
ログイン成功しました!
余談
Microsoft Edgeで開くと、
このようにパスワードのフォームに目のアイコン(パスワード表示ボタン)が表示されます。
これを削除したい場合は
::-ms-reveal {
display: none;
}
このようにアイコンのスタイルに手を加えれば良いです。
詳しくは以下を参照↓
おわりに
これが初めてのQiita投稿、初めての共同作業()です。
ゲーム本体を作ったのに私の名義で投稿するよう勧めてくれた友人の @Delphyilia 君、ありがとう。
バックエンドへの理解が浅く、Pythonで何となく書けるCGIしか手を出せていないのが現状です。
REST API?WebSocket?右も左も分からないので勉強していきたいです。