Streamlitで認証機能付きマルチページWebアプリを作成する方法
Streamlitでマルチページに対応させるため試行錯誤したので共有します。
強み
・Pythonコード形式で単調な記法
・マークダウン記述
・データサイエンス系に強い
弱み:
・組み込みの認証機能
・マルチページ機能
・より詳細なウェブページ
そのため、外部ライブラリや独自のロジックを組み合わせて実現する必要があります。
基本的に以下の2つのアプローチが考えられます。
- 外部ライブラリ
streamlit-authenticator
とファイル分割によるマルチページ - 独自の認証ロジックとセッションステート、ページ関数によるマルチページ
今回は、より手軽で推奨される1つ目のアプローチを詳しく解説します。
1. 外部ライブラリ streamlit-authenticator
とファイル分割によるマルチページ
この方法が最も一般的で、実装も比較的容易です。
必要なライブラリのインストール
まず、必要なライブラリをインストールします。
pip install streamlit streamlit-authenticator PyYAML
-
streamlit
: Webアプリ本体 -
streamlit-authenticator
: 認証機能を提供 -
PyYAML
: ユーザー情報をYAMLファイルで管理するために必要
プロジェクトのディレクトリ構成
以下のようなディレクトリ構成を推奨します。
.
├── app.py
├── config.yaml
├── pages/
│ ├── page1.py
│ └── page2.py
└── requirements.txt
-
app.py
: メインのアプリケーションファイル。認証ロジックとページ遷移を制御します。 -
config.yaml
: ユーザー情報や認証設定を格納します。 -
pages/
: 各ページを定義するPythonファイルを格納するディレクトリです。 -
requirements.txt
: アプリケーションの依存関係を記述します。
各ファイルのコード例
config.yaml
(ユーザー情報の設定)
credentials:
usernames:
jsmith:
email: jsmith@gmail.com
name: John Smith
password: abc # 実際にはハッシュ化されたパスワードを使用することを強く推奨
rbriggs:
email: rbriggs@gmail.com
name: Rebecca Briggs
password: def # 実際にはハッシュ化されたパスワードを使用することを強く推奨
cookie:
expiry_days: 30
key: random_signature_key # 秘密鍵。適当な文字列を設定してください
name: some_cookie_name
preauthorized:
emails:
- melsby@gmail.com
重要: password
はプレーンテキストで記述していますが、これは開発用です。本番環境では必ずハッシュ化されたパスワードを使用してください。 streamlit-authenticator
は内部でパスワードのハッシュ化(stauth.Hasher
)をサポートしています。
例:パスワードをハッシュ化する場合のapp.py
での利用方法(後述)
import streamlit_authenticator as stauth
hashed_passwords = stauth.Hasher(['abc', 'def']).generate()
# config.yamlにはハッシュ化されたパスワードを設定
# credentials:
# usernames:
# jsmith:
# password: <ハッシュ化されたパスワード>
app.py
(メインアプリケーション)
import streamlit as st
import streamlit_authenticator as stauth
import yaml
from yaml.loader import SafeLoader
# 認証設定の読み込み
with open('./config.yaml') as file:
config = yaml.load(file, Loader=SafeLoader)
authenticator = stauth.Authenticate(
config['credentials'],
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days'],
config['preauthorized']
)
# ログインフォームの表示
name, authentication_status, username = authenticator.login('Login', 'main')
if authentication_status:
authenticator.logout('Logout', 'main', key='unique_key')
st.write(f'Welcome *{name}*')
st.title('Multi-Page Web App')
# 認証成功後のページ遷移ロジック
# Streamlitのセッションステートを利用して現在のページを管理
if 'current_page' not in st.session_state:
st.session_state.current_page = 'home' # 初期ページ
st.sidebar.title("Navigation")
if st.sidebar.button("Home"):
st.session_state.current_page = 'home'
if st.sidebar.button("Page 1"):
st.session_state.current_page = 'page1'
if st.sidebar.button("Page 2"):
st.session_state.current_page = 'page2'
# 各ページの読み込みと表示
if st.session_state.current_page == 'home':
st.write("これはホーム画面です。")
elif st.session_state.current_page == 'page1':
from pages import page1
page1.show_page()
elif st.session_state.current_page == 'page2':
from pages import page2
page2.show_page()
elif authentication_status == False:
st.error('Username/password is incorrect')
elif authentication_status == None:
st.warning('Please enter your username and password')
# パスワードのハッシュ化例 (config.yamlに設定する前に実行)
# hashed_passwords = stauth.Hasher(['abc', 'def']).generate()
# print(hashed_passwords)
pages/page1.py
import streamlit as st
def show_page():
st.title("ページ1")
st.write("これはページ1のコンテンツです。")
st.button("ページ1のボタン")
pages/page2.py
import streamlit as st
def show_page():
st.title("ページ2")
st.write("これはページ2のコンテンツです。")
st.checkbox("ページ2のチェックボックス")
アプリケーションの実行
プロジェクトのルートディレクトリで以下のコマンドを実行します。
streamlit run app.py
ブラウザで開かれたStreamlitアプリにアクセスし、設定したユーザー名とパスワードでログインしてみてください。ログイン成功後、サイドバーに表示されたボタンでページを切り替えることができるはずです。
2. 独自の認証ロジックとセッションステート、ページ関数によるマルチページ
この方法は、streamlit-authenticator
のような外部ライブラリを使わずに、Streamlitの基本的な機能だけで認証とマルチページを実現するものです。より細かいカスタマイズが可能ですが、認証ロジックの実装(パスワードのハッシュ化、セッション管理など)をすべて自身で行う必要があります。
基本的な考え方:
- 認証: ユーザー名とパスワードの入力フォームを作成し、入力された情報が正しいかチェックします。パスワードは必ずハッシュ化して比較します。
-
セッション管理:
st.session_state
を利用して、ユーザーのログイン状態(st.session_state.logged_in = True
など)や現在の表示ページを管理します。 -
マルチページ: 各ページを関数として定義し、
st.session_state.current_page
の値に応じて表示する関数を切り替えます。
実装のポイント:
-
パスワードのハッシュ化:
bcrypt
やpasslib
などのライブラリを使用します。 -
セッション管理: ログイン状態やユーザー情報を
st.session_state
に格納します。 -
ページ遷移: サイドバーのボタンなどで
st.session_state.current_page
の値を変更し、メインコンテンツを再描画します。
このアプローチは、streamlit-authenticator
を使用するよりも多くのコード記述とセキュリティ対策の知識が必要になります。 特に本番環境での運用を考える場合、認証のセキュリティを確保するためには十分な検討が必要です。
その他の考慮事項とヒント
-
パスワードのハッシュ化: 繰り返しになりますが、本番環境では絶対にプレーンテキストのパスワードを使わないでください。
streamlit-authenticator
が提供するstauth.Hasher
を活用するか、bcrypt
などの強力なハッシュ関数を使用してください。 -
ユーザー情報の管理:
config.yaml
の代わりに、データベース(SQLite, PostgreSQLなど)やクラウドの認証サービス(Firebase Authentication, AWS Cognitoなど)と連携することも可能です。 - Streamlitの再実行: Streamlitは、コードに変更があったり、ウィジェットが操作されたりすると、スクリプト全体を上から下に再実行する特性があります。この特性を理解し、セッションステートを適切に利用することが重要です。
- CSSでのスタイリング: Streamlitのデフォルトの見た目だけでなく、カスタムCSSを適用してよりリッチなUIを作成することも可能です。
- デプロイ: 作成したアプリは、Streamlit Cloud、Heroku、Google Cloud Run、AWS Fargateなど、様々なプラットフォームにデプロイできます。
まとめ
Streamlitで認証機能付きのマルチページWebアプリを作成するには、streamlit-authenticator
のような外部ライブラリを利用するのが最も簡単で推奨される方法です。これにより、認証ロジックの実装の手間を大幅に削減できます。
もし、より細かい制御や独自の認証フローが必要な場合は、Streamlitのセッションステートと組み合わせて独自のロジックを実装することも可能ですが、セキュリティ面での考慮がより重要になります。
発展アイデア
Webアプリとして限定した場合の活用
・OSライブラリなど組み合わせ、バックエンドのコードを実行させ、Streamlitのみで完結させる。
複数フレームワーク組み合わせ
・複雑な仕組みを作ろうとした場合はFastAPIと組み合わせより工夫ができるかもしれません。
ご不明な点がありましたら、お気軽にご質問ください!