LoginSignup
4
1

More than 1 year has passed since last update.

pythonを使ってリアクティブなWebアプリを作りたい【開発編4】パスワードの暗号化

Last updated at Posted at 2021-07-21

こちらの続きです。徐々にパワーアップしていきましょう。

pythonを使ってリアクティブなWebアプリを作りたい【開発編3-2】

今回は、最初にサボったユーザー作成&パスワード保存部分の改良になります。
ハッキングで生パスワードが漏れたとか、サービス登録後に平文のパスワードがメールで送られてきたとか。流石にだんだん聞かなくはなってきましたが、たまに耳にします。それはだめだ。
ということで、パスワードの暗号化と、それを使ったログイン機能の提供です。

今回変更したファイル

参考にしたQiita

Flaskで始めるSNSチュートリアル

何をしたのか

.envの追記

export SECRET_KEY="Put*YOUR*SECRET*KEY"

環境変数を一つ追加してあります。
Put*YOUR*SECRET*KEY
部分はご自分のキーに変更してください。何でも良いです。ランダム文字列にしましょう。

flask_bcryptのインストール

requirements.txtにかかれていますが、flask_bcryptをインストールしました。
pipenv install flask_bcrypt
してあります。

models.pyの追記

backend/models.py

backend/models.py
from flask_bcrypt import generate_password_hash, check_password_hash

class User(UserMixin, db.Model):
#中略
    def __init__(self, email, password):
        """ ユーザ名、メール、パスワードが入力必須 """
        self.email = email
        self.password = generate_password_hash(password).decode('utf-8')

    def check_password(self, password):
        """ パスワードをチェックしてTrue/Falseを返す """
        return check_password_hash(self.password, password)

    def reset_password(self, password):
        """ 再設定されたパスワードをDBにアップデート """
        self.password = generate_password_hash(password).decode('utf-8')

    @classmethod
    def select_by_email(cls, email):
        """ UserテーブルからemailでSELECTされたインスタンスを返す """
        return cls.query.filter_by(email=email).first()

こちらを追記してあります。

flask-migrateDB.pyの微調整

backend/flask-migrateDB.py
こちらには暗号化のキーを読み込ませる必要があります。

backend/flask-migrateDB.py
app = Flask(__name__)
# データベースファイルは実行ファイルと同じ場所にapp.dbという名前で作成
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get("SQLALCHEMY_DATABASE_URI") or "sqlite:///app.sqlite3"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY") #←こちらを追記

auth.pyの微調整

backend/auth.py
@auth.route("/auth/login", methods=["POST"])
def login():
    email = request.json.get("username", None)
    password = request.json.get("password", None)
    user = User.select_by_email(email)
    print('/auth/login')
    print(user)
    if user and user.check_password(password):
        """ ユーザに対してログイン処理を施す """
        return jsonify(
            access_token='test'
            ,expires_in=3600
            ,user_id=user.id
            ), 200
    elif user:
        return jsonify({"message": "メールアドレスとパスワードの組み合わせが間違っています。"}), 400
    else:
        return jsonify({"message": "存在しないユーザです"}), 400

ユーザの認証方法が
1:メールアドレスでまずはユーザーを取得
user = User.select_by_email(email)
2:ユーザが存在する場合はuser.check_password(password)でパスワードのマッチングをチェックする

というやり方になっています。

登録時にパスワードを暗号化する

/auth/register
で行っている処理は前とほぼ変えていません。それでも暗号化されているのはなぜかというとモデルに答えがあります。

backend/models.py
    def __init__(self, email, password):
#中略
        self.password = generate_password_hash(password).decode('utf-8')

ここですね。この設定があることによって暗号化されるという訳です。

最後に登録されたテーブルを見てみましょう

user_–_q4_–_qa4u.png

最初のadminは暗号化前です。
それ以下が.envのSECRET_KEYを使って暗号化されたパスワードとなっていることが分かります。

関連リンク

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1