質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4180閲覧

ユーザー認証時のハッシュ化したパスワードの照合について

gabri_1207

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2021/03/10 11:49

編集2021/03/10 14:01

プログラミング初心者です。
現在、WebアプリをPythonのフレームワークFastAPIで作成中です。
ログイン認証機能を作成していますが、DBのハッシュ化して格納しているパスワードとログイン時に入力したパスワードをハッシュ化して、照合し、ユーザー認証を行いたいのですが、パスワードが一致せず、困っております。
以下のように書いております。

from typing import Optional from datetime import datetime, timedelta from fastapi import APIRouter, Depends, HTTPException from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jose import jwt from passlib.context import CryptContext from settings.db import session from models.users import Users from schemas.users import UserResponse from schemas.admin import Tokens router = APIRouter() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") OAuth2_scheme = OAuth2PasswordBearer(tokenUrl="token") def authenticate(name:Optional[str]=None, password:Optional[str]=None): """ユーザーの認証  """ check_password=pwd_context.hash(password) session.commit() user = session.query(Users).filter(Users.name == name).first() if pwd_context.verify(user.password, check_password) == False: raise HTTPException(status_code=401, detail="パスワードが違います。") return user

hashlib.contextの使い方が良くないのでしょうか。
コードに不備があれば、ぜひ教えて頂きたいです。
下記は、エラー内容です。

api | 2021-03-10 06:52:25,539 INFO sqlalchemy.engine.base.Engine COMMIT api | 2021-03-10 06:52:25,717 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) api | 2021-03-10 06:52:25,725 INFO sqlalchemy.engine.base.Engine SELECT `groups`.id AS groups_id, `groups`.created_at AS groups_created_at, `groups`.updated_at AS groups_updated_at, `groups`.name AS groups_name, `groups`.description AS groups_description, `groups`.capacity AS groups_capacity, `groups`.number_of_members AS groups_number_of_members api | FROM `groups`, users_groups api | WHERE %s = users_groups.user_id AND `groups`.id = users_groups.group_id ORDER BY `groups`.id api | 2021-03-10 06:52:25,726 INFO sqlalchemy.engine.base.Engine (11,) api | 2021-03-10 06:52:25,825 INFO sqlalchemy.engine.base.Engine ROLLBACK api | INFO: 172.18.0.1:36596 - "POST /v0/users HTTP/1.1" 200 OK api | 2021-03-10 06:52:56,551 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) api | 2021-03-10 06:52:56,567 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name, users.email AS users_email, users.password AS users_password, users.age AS users_age, users.gender AS users_gender, users.height AS users_height, users.weight AS users_weight, users.kind_of_sport AS users_kind_of_sport, users.type_of_team AS users_type_of_team, users.years_of_experience AS users_years_of_experience, users.group_id AS users_group_id, users.last_login AS users_last_login, users.created_at AS users_created_at, users.updated_at AS users_updated_at api | FROM users api | WHERE users.name = %s api | LIMIT %s api | 2021-03-10 06:52:56,568 INFO sqlalchemy.engine.base.Engine ('Taro', 1) api | INFO: 172.18.0.1:36602 - "POST /v0/admin/token HTTP/1.1" 401 Unauthorized

併せて、user.passwordとcheck_passwordの出力した値も記入しておきます。

2021-03-10 13:17:57,278 INFO sqlalchemy.engine.base.Engine ('Taro', 1) api | $2b$12$QI/qWujhn/eHbSnU2CZv0erEW8hPm.ZLshyl1ovkjVVL9Fz/qWru. api | $2b$12$SZg747mCOKtf1b4928Zz1OIBp5uQOZRoiU72KQyTJxWHAyoIk30dm api | INFO: 172.19.0.1:46922 - "POST /v0/admin/token HTTP/1.1" 401 Unauthorized

この場合、ハッシュの仕方に不備があるのでしょうか?
どちらもハッシュ化前のサンプルパスワードは「baseball11」としています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2021/03/10 11:54

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
gabri_1207

2021/03/10 11:59

依頼ありがとうございます。 慣れたおらず失礼致しました。 修正致しました。
t_obara

2021/03/10 12:49

「user.password」とか「password」の内容が同一であることは確認されたのですか?特にエラーは出ていないのですよね?
gabri_1207

2021/03/10 13:03

ご質問ありがとうございます。 失礼いたしました、出てきたエラー文も追加いたしました。 ご質問に関して、引数のpasswordをform_passwordと変更してみましたが、同じエラーになりました。
guest

回答2

0

ベストアンサー

from passlib.context import CryptContext
pwd_context.verify(user.password, check_password)

の「pwd_context.verify(user.password, check_password)」では、user.passwordの部分は、平文である必要があります。つまりverifyに成功するためには、user.passwordが"baseball11"である必要があります。

なぜなら、このhashとはsha1のような、単にハッシュ関数の結果ではなく、結果自体が暗号されてます。いわゆるHMACを生成していると思えばいいです。

$2b$12$SZg747mCOKtf1b4928Zz1OIBp5uQOZRoiU72KQyTJxWHAyoIk30dm

の「$2b$12」の部分はいわばヘッダのようなものです。本当に純粋なハッシュ関数であれば、先頭が一致することはあり得ません。

なので、パスワードそのものをDBに格納しない場合、hashlib.contextを使うのではなく、純粋にハッシュ関数(sha256)を使えばいいと思います。

あるいは、DB(user.password)にHASHの結果を格納しているのだとしたら、以下でも行けるはずです。

pwd_context.verify(password, user.password)

投稿2021/03/10 15:53

編集2021/03/10 15:59
torofieldchan

総合スコア39

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gabri_1207

2021/03/11 06:41

回答ありがとうございました。 解決することができました。 詳しい説明で仕組みを理解することができました。
guest

0

コードから、user.passwordとpasswordに"baseball11"べきだと思います。それが同一なのかを確認しているの?と言う質問です。ログに出力するなどして確認してみては?あるいは固定値を設定してみるとか。

python

1 2from passlib.context import CryptContext 3myctx = CryptContext(schemes=["bcrypt"], deprecated="auto") 4crypted = myctx.hash("obara") 5print(myctx.verify("obara", crypted))

この結果はTrueとなります。

投稿2021/03/10 14:29

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問