Flaskでフォーム機能の作成

これまでFlaskの仕様についてまとめたり
FlaskでAPIを作成したりしてみました

・Flask入門 〜Pythonのフレームワーク〜
https://qiita.com/wooooo/items/e9f96c10f870c5124d8b

・Flaskの環境構築手順
https://qiita.com/wooooo/items/195f90b483aaafdf765f

・Flaskで動的なWebアプリを作成
https://qiita.com/wooooo/items/77a50edd4620891894b4

今回はFlaskのテンプレートを作成してフォーム機能を作成していきます

# フォーム機能
FlaskのHTMLテンプレートでは、フロント側でユーザの入力した値を受け取り、処理したり保存したりできます
Flaskはテンプレートのフォーム機能とユーザの入力値を処理できる仕組みがあります。
FlaskにWTFormsというライブラリが組み込まれており、これを使用してユーザの入力データを検証したりできます

・WTFormsについて

https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/patterns/wtforms.html

WTFormsを使ってログイン画面を例にフォーム機能を実装していきます

## WTFormsのインストール
WTFormsをインストールします
```
pip install WTForms
```

## フォーム機能の定義
ログイン画面のフォーム機能を定義します

```python:form.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, Length

class Form(input):
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired(), Length(min=8)])
    submit = SubmitField('Login')
```

このコードでは'Email'と'Password'の2つの入力フィールドを定義しています

各フィールドの検証機能を設定するために、validatorsという引数を設定しています

Emailの"validators=[DataRequired(), Email()]"は
・DataRequired()
　　必須項目を定義
・Email()
　　メールアドレスの形式か検証

passwordのvalidatorsの"Length(min=8)"は
パスワードの文字列が8文字以上入力されていることを検証しています

・validatorsについて
https://wtforms.readthedocs.io/en/2.3.x/validators/

# ビュー定義
フォームの定義が作成できたので、viewに先ほど作成した定義をレンタリングして、
ユーザが入力したデータを処理できるようにします

```python:view.py
from flask import render_template, request
from .form import Form # 先ほど作成したクラスをimport

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = Form()
    if form.validate_on_submit():
        email = form.email.data
        password = form.password.data
        # 入力値を使って処理（省略）
    return render_template('login.html', form=form)
```

このコードではGETとPOSTのHTTPメソッドを受け取ることができます
ユーザが/loginのURLにアクセスすると、login()が呼び出され
先ほど作成したフォームの作成とバリデーションチェック機能を提供します
ユーザがフォームに入力されたデータを処理することができます

# テンプレート作成
画面上にフォーム画面としてのHTMLテンプレートを作成していきます
```html:login.html
<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
</head>
<body>
    <h1>Login</h1>
    <form method="POST">
      {{ form.csrf_token }}
      <div>
        {{ form.email.label }} {{ form.email() }}
        {% for error in form.email.errors %}
        <span style="color: red;">[{{ error }}]</span>
        {% endfor %}
      </div>
      <div>
        {{ form.password.label }} {{ form.password() }}
        {% for error in form.password.errors %}
          <span style="color: red;">[{{ error }}]</span>
        {% endfor %}
      </div>
      {{ form.submit() }}
    </form>
</body>
</html>
```

{{ form.csrf_token }}はクロスサイト・リクエスト・フォージェリ (CSRF) 攻撃対策に定義しています

以上のように4記事に渡ってPythonのフレームワークのFlaskについてまとめました
Flaskはシンプルで、柔軟で使いやすいフレームワークです
小規模から大規模なアプリまで幅広く対応可能で、シンプルさが故に習得しやすいです。

# 備考
・クロスサイト・リクエスト・フォージェリ (CSRF)について
https://www.ipa.go.jp/security/vuln/websecurity/csrf.html

攻撃に流れは
1.攻撃者は悪意のあるウェブサイトやメールなどを通じて、被害者のブラウザに特定のリンクやイメージを含むコンテンツを表示します

2.被害者が攻撃者のサイトを訪れると、そのサイト内で自動的に攻撃が実行されます

3.攻撃者のサイト内には、被害者がアクセスしているターゲットのWebアプリケーションへのリクエストを自動的に生成する悪意のあるコードが含まれています

4.被害者のブラウザは、攻撃者の指示に従って悪意のあるリクエストをターゲットのWebアプリケーションに送信します。このリクエストは、被害者の認証情報やセッション情報を含んでいる場合があります

5.ターゲットのWebアプリケーションは、被害者のブラウザからのリクエストが信頼できるものであると誤って判断し、攻撃が実行されます。これにより、被害者の意図しないアクション（例：パスワード変更、注文の実行など）が実行される可能性があります