PythonでFlaskを使用しREST APIを保護する(Basic認証を設定する)

PythonでFlaskを使用しREST APIを保護、もしくはBasic認証を設定してみます。

今回は、FlaskとFlask-HTTPAuthを用います。この2つのライブラリは、Pythonの標準ライブラリではありませんので、事前にインストールする必要があります。

■Python

今回のPythonのバージョンは、「3.8.5」を使用しています。(Windows10)(pythonランチャーでの確認)

■プロジェクトディレクトリを作成する

PythonでFlaskを使用しREST APIを保護してみますが、その前に仮想環境の構築を行います。構築するために、プロジェクトディレクトリを作成します。

今回は「C:\Users\user_(フォルダパス)」内に「flask-auth」ディレクトリという空のプロジェクトディレクトリを作成しました。

■プロジェクトディレクトリへ移動する

作成後、Windows10のコマンドプロンプトを起動します。

C:\Users\user_>cd flask-auth

起動後、上記のコマンドを入力し、Enterキーを押します。「cd」コマンドで「flask-auth」ディレクトリ内に移動します。

■仮想環境を作成する

C:\Users\user_\flask-auth>py -3.8 -m venv .venv

移動後、上記のコマンドを入力し、Enterキーを押します。本来だと「python -m venv .venv」で仮想環境のディレクトリ「.venv」を作成しますが、今回はPythonのバージョンを指定しています。なお、今回仮想環境のディレクトリ名は「.venv」としていますが、ご自身で変更は可能です。

Enterキーを押すと、何も出力されませんが、これで仮想環境の作成が完了となります。

■仮想環境への切り替え

C:\Users\user_\flask-auth>.venv\Scripts\activate.bat

完了後、上記のコマンドを入力し、Enterキーを押します。仮想環境のディレクトリ内に作成された activateスクリプトを実行し、仮想環境に入ります。

(.venv) C:\Users\user_\flask-auth>

Enterキーを押すと、「(.venv)」と表示されます。これで仮想環境に入ることができました。

■FlaskとFlask-HTTPAuthのインストール

(.venv) C:\Users\user_\flask-auth>pip install flask
(.venv) C:\Users\user_\flask-auth>pip install Flask-HTTPAuth

仮想環境に入った後に、上記のコマンドを1つずつ入力し、Enterキーを押していきます。これでpipを経由してFlaskとFlask-HTTPAuthをインストールします。

Collecting flask
  Using cached Flask-2.1.2-py3-none-any.whl (95 kB)
Collecting Jinja2>=3.0
  Using cached Jinja2-3.1.2-py3-none-any.whl (133 kB)
Collecting itsdangerous>=2.0
  Using cached itsdangerous-2.1.2-py3-none-any.whl (15 kB)
Collecting Werkzeug>=2.0
  Using cached Werkzeug-2.1.2-py3-none-any.whl (224 kB)
Collecting importlib-metadata>=3.6.0; python_version < "3.10" Downloading importlib_metadata-4.12.0-py3-none-any.whl (21 kB) Collecting click>=8.0
  Using cached click-8.1.3-py3-none-any.whl (96 kB)
Collecting MarkupSafe>=2.0
  Using cached MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl (17 kB)
Collecting zipp>=0.5
  Downloading zipp-3.8.1-py3-none-any.whl (5.6 kB)
Collecting colorama; platform_system == "Windows"
  Downloading colorama-0.4.5-py2.py3-none-any.whl (16 kB)
Installing collected packages: MarkupSafe, Jinja2, itsdangerous, Werkzeug, zipp, importlib-metadata, colorama, click, flask
Successfully installed Jinja2-3.1.2 MarkupSafe-2.1.1 Werkzeug-2.1.2 click-8.1.3 colorama-0.4.5 flask-2.1.2 importlib-metadata-4.12.0 itsdangerous-2.1.2 zipp-3.8.1
Collecting Flask-HTTPAuth
  Downloading Flask_HTTPAuth-4.7.0-py3-none-any.whl (6.9 kB)
Requirement already satisfied: flask in c:\users\user_\flask-auth\.venv\lib\site-packages (from Flask-HTTPAuth) (2.1.2)
Requirement already satisfied: Jinja2>=3.0 in c:\users\user_\flask-auth\.venv\lib\site-packages (from flask->Flask-HTTPAuth) (3.1.2)
Requirement already satisfied: importlib-metadata>=3.6.0; python_version < "3.10" in c:\users\user_\flask-auth\.venv\lib\site-packages (from flask->Flask-HTTPAuth) (4.12.0)
Requirement already satisfied: itsdangerous>=2.0 in c:\users\user_\flask-auth\.venv\lib\site-packages (from flask->Flask-HTTPAuth) (2.1.2)
Requirement already satisfied: Werkzeug>=2.0 in c:\users\user_\flask-auth\.venv\lib\site-packages (from flask->Flask-HTTPAuth) (2.1.2)
Requirement already satisfied: click>=8.0 in c:\users\user_\flask-auth\.venv\lib\site-packages (from flask->Flask-HTTPAuth) (8.1.3)
Requirement already satisfied: MarkupSafe>=2.0 in c:\users\user_\flask-auth\.venv\lib\site-packages (from Jinja2>=3.0->flask->Flask-HTTPAuth) (2.1.1)
Requirement already satisfied: zipp>=0.5 in c:\users\user_\flask-auth\.venv\lib\site-packages (from importlib-metadata>=3.6.0; python_version < "3.10"->flask->Flask-HTTPAuth) (3.8.1)
Requirement already satisfied: colorama; platform_system == "Windows" in c:\users\user_\flask-auth\.venv\lib\site-packages (from click>=8.0->flask->Flask-HTTPAuth) (0.4.5)
Installing collected packages: Flask-HTTPAuth
Successfully installed Flask-HTTPAuth-4.7.0

Enterキーを押すと、上記のように「Successfully installed(正常にインストールされました)」と出力されます。これが出力されればインストールは完了となります。なお、「WARNING: You are using pip version **.*.*; however, version **.*.* is available. You should consider upgrading via the ‘c:\users\user_\flask-auth\.venv\scripts\python.exe -m pip install –upgrade pip’ command.」という警告(WARNING)が出力されることがありますが、これはあくまで警告でありエラーではないので、今回は一旦無視します。

■Flaskフレームワークを使用しREST APIを作成する

インストール後、Flaskフレームワークを使用しREST APIを作成します。今回は「flask-auth」ディレクトリ内に「api_test.py」というスクリプトファイルを作り、コードエディタを開いてファイル内にコードを書いていきます。

■コード

from flask import Flask
from flask import jsonify
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__)
auth = HTTPBasicAuth()

@app.route('/auth_test')
@auth.login_required
def get_response():
    return jsonify('このメッセージを表示する権限が与えられています。test')

if __name__ == "__main__":
    app.run()

今回はflaskモジュールでFlaskとjsonifyを呼び出し、さらにflask_httpauthモジュールでHTTPBasicAuthを呼び出します。その後、appという変数を定義し、その中でFlask(__name__)を格納し、Flaskのインスタンスを作成します。作成後、authという変数を定義し、その中でHTTPBasicAuth()を用い、インスタンスを作成します。

作成後、「@app.route()」を用いてURLとfuncitonを関連付けします。今回のURLは「/auth_test」とし、関数はget_response()という関数を定義します。さらに、「@auth.login_required」と記述し、認証が成功したときに定義した関数が呼び出されるようにします。

最後にif文を用いて「__name__ == “__main__”」と記述します。これでプログラムがPythonインタープリターによって直接実行される場合にのみ、ifステートメント内のコードを実行するようになります。今回実行するコードは「app.run()」でサーバーを起動するものです。

■実行・検証

このスクリプトを保存し、コマンドプロンプト上で仮想環境に入った状態で実行してみます。

(.venv) C:\Users\user_\flask-auth>python api_test.py

 * Serving Flask app 'api_test' (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: off
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)

実行してみると、上記のメッセージが出力され、サーバーが起動します。起動後、Webブラウザを起動し、アドレスバーに「http://127.0.0.1:5000」とアクセスしますが、今回は「http://127.0.0.1:5000/auth_test」にアクセスしてみます。

アクセスすると、「ログイン」というポップアップが表示されました。ポップアップ内にはユーザー名とパスワードを入力する欄が表示されていることが確認できました。現時点では、ユーザー名やパスワードの設定を行っていないので、ログインすることができません。しかし、今回は検証のため「キャンセル」ボタンをクリックしてみます。

クリックしてみると「Unauthorized Access(不正アクセス)」とページに表示されました。このことから、REST APIが保護されていることがわかります。ここまで実行・検証は終了します。

■ユーザー認証の処理を行う

終了後、ユーザー認証の処理を行ってみますので、「flask-auth」ディレクトリ内に「api_test.py」というスクリプトファイルを編集します。

■コード

from flask import Flask
from flask import jsonify
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__)
auth = HTTPBasicAuth()

@app.route('/auth_test')
@auth.login_required
def get_response():
    return jsonify('このメッセージを表示する権限が与えられています。test')

@auth.verify_password
def authenticate(username,password):
    if username and password:
        if username == 'admin-test' and password =='password12345':
            return True
        else:
            return False
    return False        

if __name__ == "__main__":
    app.run()

編集する内容としては「@auth.verify_password」と記述し、authenticate()という関数を定義します。この関数が呼び出されると、ユーザー名とパスワードの組み合わせが有効であることを確認します。なお、今回のユーザー名は「admin-test」とパスワードは「password12345」とします。if〜else 文を用いて、認証に失敗した場合は、False(偽)が返されます。

■実行・検証

このスクリプトを再び保存し、コマンドプロンプト上で仮想環境に入った状態で実行してみます。

(.venv) C:\Users\user_\flask-auth>python api_test.py

 * Serving Flask app 'api_test' (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: off
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)

実行してみると、先程同じくメッセージが出力され、サーバーが起動します。起動後、今回はWebブラウザを起動し、APIのテストが行えるPostmanhttps://www.postman.com/)にアクセスします。アクセス後、事前にアカウントを登録しているので、「Sign In(サインイン)」ボタンをクリックし、「Email or Username」と「Password」を入力し、サインインします。

サインイン後、Postmanのダッシュボード上部の「Workspaces」をクリックし、「My Workspace」をクリックします。

クリックすると、「Workspaces」の「My Workspace」ページが表示されますので、ページ内の「+」ボタンをクリックします。

クリックすると「Untitled Request」のタブが新しく作成されます。

作成されたタブ内の「GET」と表示された右側の入力欄に今回作成したルートである「http://127.0.0.1:5000/auth_test」を入力します。入力後、「Authorization」タブをクリックします。クリックすると、タブ内に「Type」と表示され右側に「lnherit au…」と表示された箇所があるので、こちらをクリックします。

クリックするとプルダウンメニューが表示されます。メニューの中から「Basic Auth」をクリックします。

クリックすると、左側に「Username」と「Password」の入力欄が表示されますので、「api_test.py」内で設定したusernameとpasswordをそれぞれ入力します。

入力後、「Send」ボタンをクリックします。

クリックすると、「http://127.0.0.1:5000/auth_test」にGETリクエストが送信され、今回は「Could not send request」、「Cloud Agent Error: Can not send requests to localhost. Select a different agent.」と出力されました。内容を確認すると、ユーザー認証が行われておらず、原因を調べたところ、Web版のPostmanではコンピューターのローカルホストにリクエストを送信できないということが判明したので、「Postman’s Desktop Agent(デスクトップ版)」をWindows10にインストールし、使用してみることにしました。

使用してみると、今回スクリプト内で設定したusernameとpasswordの組み合わせが有効であるかの認証が行われ、「True(真)」・有効となり、データが返され出力させることができました。

コメント

タイトルとURLをコピーしました