ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

python: Flaskアプリの作成16 ユーザーの登録③

備忘録です。

今回は、ユーザー設定にパスワードを付加し、DBにハッシュ化して保存する設定の備忘録です。

hash

werkzeugでハッシュ化

 

その1 werkzeugライブラリのインストール

# app.py

from werkzeug.security import generate_password_hash, check_password_hash

 

 

その2 Usersテーブルの編集

テーブルを編集するので一旦、これまで登録していたユーザーは削除します。特にパスワードなどを扱う場合は必ず消しておいた方が良いです。

#app.py

# ユーザー用モデル
class Users(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False)
    email = db.Column(db.String(120), nullable=False, unique=True)
    u_created_at = db.Column(db.DateTime, default=datetime.now(pytz.timezone('Asia/Tokyo')))
   # ここから追加
    password_hash = db.Column(db.String(128))

    @property
    def password(self):
        raise AttributeError('password is not a readable!')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)
    # ここまで追加
    
    # Create A String
    def __repr__(self):
        return '<Name %r>' % self.name

上記の「ここから追加」〜「ここまで追加」部分を追加します。

 

その3 flask shellでチェック

flask shellはコマンドラインインターフェイスで多くのことを自動的にやってくれるものとのことです。 Shellを使った作業 — Flask Documentation (2.0.x)

 

コマンドラインで上記の設定をチェックしてみるとこうなります。

$ flask shell

>>> from app import Users
# uというユーザーを作成 >>> u = Users() >>> u.password = 'reo' >>> u.password Traceback (most recent call last): File "<console>", line 1, in <module> File "/Users/yourfolda/app.py", line 114, in password raise AttributeError('password is not a readable!') AttributeError: password is not a readable!

u.passwordのところでハッシュを作っていないのでエラーを吐き出しています。

 

>>> u.password_hash
'pbkdf2:sha256:260000$TdDFXjnQWPjEHvKo$514ee6d136c6c29857b7d00ab679a09313ac34dc9503858926e295b97c820344'
>>> u.verify_password('reo')
True
>>> 

setterが起動してpasswordのハッシュができたようです。

最後にverify_password関数で確認するとこのハッシュのパスワードが'reo'であることが確認できます。

 

その4 DBにプッシュ

モデルの修正をしたのでDBにプッシュします。

$ flask db migrate -m 'コメント'
$ flask db upgrade

 

その5 ユーザー追加用フォームにパスワードの入力欄を追加

# add_user.html

  <form method="POST">
    {{ form.hidden_tag() }}

    {{ form.name.label(class="form-label") }}
    {{ form.name(class="form-control") }}
    <br/>

    {{ form.email.label(class="form-label") }}
    {{ form.email(class="form-control") }}
    <br/>

    # パスワード入力欄の追加
    {{ form.password_hash.label(class="form-label") }}
    {{ form.password_hash(class="form-control") }}
    <br/>

    # 確認用パスワード入力欄の追加
    {{ form.password_hash2.label(class="form-label") }}
    {{ form.password_hash2(class="form-control") }}
    <br/>


    {{ form.submit(class="btn btn-secondary") }}

  </form>

 

その6 フォームの編集

# ユーザーを投稿するフォーム
class UserForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired()])
    password_hash = PasswordField('Password', validators=[DataRequired(), EqualTo('password_hash2', message='Password Must Match!')])
    password_hash2 = PasswordField('Confirm Password', validators=[DataRequired()])
    submit = SubmitField('Submit')

PasswordFieldでセットすると、入力時に[・・・・・]という感じで表向き表示されないようなフィールドとなります。

 

その7 ユーザーを登録する関数を編集

# app.py

# ユーザーを登録するページ
@app.route('/user/add', methods=['GET', 'POST'])
def add_user():
    name = None
    form = UserForm()
    if form.validate_on_submit():
        # ユニークチェック
        user = Users.query.filter_by(email=form.email.data).first()
        if user is None:  
# passwordをhash化する          
hashed_pw = generate_password_hash(form.password_hash.data, "sha256")
            # hash化したpassword_hashのデータをDBに保存するようにセット
                        user = Users(name=form.name.data, email=form.email.data, password_hash=hashed_pw)             db.session.add(user) db.session.commit() name = form.name.data form.name.data = '' form.email.data = '' # 登録後フォームの中身を空にします form.password_hash.data = '' our_users = Users.query.order_by(Users.u_created_at) return render_template('add_user.html', form=form, name=name, our_users=our_users)

generate_password_hash関数を呼び出してパスワードをハッシュ化する必要があります。そしてハッシュ化したパスワードをDBに登録します。