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

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

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

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python

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

Q&A

解決済

2回答

2316閲覧

flask_wtf の FileFiled から受け取ったファイルの中身をハッシュ化したい

tomiharu1017

総合スコア4

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python

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

0グッド

0クリップ

投稿2020/07/31 07:31

flask_wtfのFileFieldから受け取ったファイルの中身をハッシュ化してデータベースに登録しようとしたのですが,どのファイルを選択しても登録されるハッシュ値が同じになってしまいます.おそらくFileStorage object に原因があるのだと思うのですが,わかる方は教えていただけないでしょうか.FileFieldではファイルの中身を読み込めないのであれば,どのようにすればよいか教えてください.よろしくお願いいたします.

必要なimportは全て行われており,エラーは出ていないのでそこには問題はないと思います.

データを受け取るFileFieldはこれになります.

python

1class MalwareRegistrationForm(FlaskForm): 2 malware_name = StringField('Malware Name', validators=[DataRequired()]) 3 malware_file = FileField('Choose Malware file', validators=[FileRequired()]) 4 submit = SubmitField('Register') 5 6 def validate_malware_file(self, malware_file): 7 target = generate_file_hash(self.malware_file.data) 8 9 if Malware.query.filter_by(malware_hash=target).first(): 10 raise ValidationError('Malware hash has been registerd already!')

受け取ったファイルのハッシュ値を計算する関数はこれです.

python

1def generate_file_hash(file): 2 3 file_content = file.read() 4 file_content = hashlib.sha256(file_content) 5 return file_content.hexdigest()

ファイルを登録するデータベースのクラスがこれです.

python

1class Malware(db.Model, UserMixin): 2 3 __tablename__ = 'malware' 4 5 id = db.Column(db.Integer, primary_key = True) 6 malware_name = db.Column(db.String(64), index=True) 7 malware_hash = db.Column(db.String(128)) 8 9 # ファイルを受け取ってハッシュ化してのち登録 10 def __init__(self, malware_name, malware_file): 11 self.malware_name = malware_name 12 self.malware_hash = generate_file_hash(malware_file)

そして,ファイルの選択及びアップロード画面のview.py部分がこれです

python

1@check_blueprint.route('/addmalware', methods=['GET', 'POST']) 2@login_required 3def malware_register(): 4 form = MalwareRegistrationForm() 5 6 if form.validate_on_submit(): 7 malware = Malware(malware_name=form.malware_name.data, 8 malware_file=form.malware_file.data) 9 10 db.session.add(malware) 11 db.session.commit() 12 flash('Successfully registerd.') 13 return redirect(url_for('index')) 14 15 return render_template('register_malware.html', form=form)

なにか少しでも気付いたことがありましたら教えていただけると幸いです.

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

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

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

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

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

guest

回答2

0

自己解決

結局FileFieldの使用は諦め,以下のコードにすることで解決しました.

ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'exe'} def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@check_blueprint.route('/check', methods=['GET', 'POST']) def upload_file(): flag = '' name = '' if request.method == 'POST': # check if the post request has the file part if 'file' not in request.files: flash('No file part') file = request.files['file'] # if user does not select file, browser also # submit an empty part without filename filename = file.filename if filename == '': flash('No selected file') if file and allowed_file(filename): filename = secure_filename(filename) filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(filepath) hash_val = generate_file_hash(filepath) malware = Malware.query.filter_by(malware_hash=hash_val).first() os.remove(filepath) if malware is not None: flag = 'True' name = malware.malware_name else: flag = 'False' # result = History(is_malware=str(flag), file_hash=hash_val) result = History(is_malware=flag, hash_val=hash_val) db.session.add(result) db.session.commit() elif allowed_file(filename) == False: flash("Your file's extension is not accepted.") else: pass return render_template('select_file.html', flag=flag, name=name)
def generate_file_hash(filepath): with open(filepath) as file: binary = file.read() hash_val = hashlib.sha256(binary.encode('utf-8')).hexdigest() return hash_val

ご協力ありがとうございました.

投稿2020/08/04 03:20

tomiharu1017

総合スコア4

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

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

0

以下のような単純な例でハッシュ値を計算できました。
コード全体が分からないですが、正常にアップロードされたファイルデータを取得できていないのではないでしょうか。

Python

1from flask import Flask, render_template 2from flask_wtf import FlaskForm 3from flask_wtf.file import FileField, FileRequired 4from wtforms import SubmitField 5import hashlib 6 7class FileForm(FlaskForm): 8 file = FileField(validators=[FileRequired()]) 9 submit = SubmitField('Upload') 10 11app = Flask(__name__) 12app.config['SECRET_KEY'] = 'hoge' 13 14@app.route("/", methods=['GET', 'POST']) 15def upload(): 16 form = FileForm() 17 if form.validate_on_submit(): 18 f = form.file.data 19 data = f.read() 20 hash = hashlib.sha256(data) 21 print(data, hash.hexdigest()) 22 # b'abc' ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 23 24 return render_template('index.html', form=form) 25 26if __name__ == "__main__": 27 app.run(debug=True)

index.html

HTML

1<!doctype html><html lang="ja"> 2<head><meta charset="UTF-8"><title>アップロード</title></head> 3<body> 4<form method="POST" enctype="multipart/form-data"> 5 {{ form.hidden_tag() }} 6 {{ form.file }} 7 {{ form.submit }} 8</form> 9</body> 10</html>

実行結果

* Serving Flask app "sv" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Restarting with windowsapi reloader * Debugger is active! * Debugger PIN: 256-310-102 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) 127.0.0.1 - - [04/Aug/2020 13:04:34] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [04/Aug/2020 13:04:34] "GET /favicon.ico HTTP/1.1" 404 - b'abc' ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 127.0.0.1 - - [04/Aug/2020 13:04:55] "POST / HTTP/1.1" 200 - b'def' cb8379ac2098aa165029e3938a51da0bcecfc008fd6795f401178647f96c5b34 127.0.0.1 - - [04/Aug/2020 13:05:16] "POST / HTTP/1.1" 200 -

投稿2020/08/02 11:03

編集2020/08/04 04:10
can110

総合スコア38341

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

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

tomiharu1017

2020/08/04 03:17

回答ありがとうございます.私も初めにこのコードを試したのですが,この場合だと全てのファイルに対して同じハッシュ値を返してしまうのです.読み込んだ内容をprint()してみたのですが,中身は空でした.
can110

2020/08/04 04:11

回答コードを実際に動作させてみましたか?正常に動作します。 コメントにあるような現象を示す実行結果を提示ください。
tomiharu1017

2020/08/04 05:14

今試したところcan110さんのコードが正常に動作しました!コードのロジックは私のものと同じはずなのですが... しかしFileFieldでもできることが分かったので,もう一度確認してみます. 本当にありがとうございました.
tomiharu1017

2020/08/04 05:22 編集

ところで,このようにform.file.dataのようにしてハッシュ化するコードはセキュリティの観点からして安全と言えるのでしょうか?もし何か知見がありましたら教えていただけると幸いです.厚かましくて申し訳ありません.
can110

2020/08/04 05:40

何をもって安全とみなすかによるかと思いますが、任意のバイナリからハッシュ値を求める処理自体には問題はないように思います。
tomiharu1017

2020/08/04 05:46

了解しました.丁寧な対応ありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問