Flaskの拡張機能
Flask-Mail
まずはコードをみてみましょう。
code: python
from flask import Flask
from flask_mail import Mail, Message
MAIL_DEFAULT_SENDER = "iisaka51@gmail.com"
MAIL_SERVER='localhost'
MAIL_PORT=None
MAIL_USE_TLS=True
MAIL_USERNAME=''
app = Flask(__name__)
app.config.from_object(__name__)
mail = Mail(app)
msg = Message(subject="test",
msg.body = """
Please ignore me.
This is just for mail system.
"""
mail = app.extensions.get("mail")
mail.send(msg)
Flask のインスタンスオブジェクト app を flask_mail の Mail クラスに与えて初期化するだけです。
この例では、ローカルマシンで認証なしにメールが送信できる設定の場合です。
もし、認証が必要になるのであれば MAIL_USER と MAIL_PASSWORD を設定します。
例えばGMAILのSMTPサーバに接続してメールを送信するような場合の設定は次のようになります。
code: python
MAIL_SERVER='smtp.gmail.com'
MAIL_PORT=587
MAIL_USE_TLS=True
MAIL_USERNAME='GMAILアカウント(xxxx@gmail.com)'
MAIL_USERPASSWORD='GMAILアカウントのパスワード'
MAIL_DEFAULT_SENDER='GMAILアカウント(xxxx@gmail.com)'
GMAIL の場合は、使用するGoogleアカウントで「安全性の低いアプリのアクセス」を許可する必要があります。
Googleアカウントの「アカウントを管理」
「セキュリティ」を選択
表示される画面の下部にある「安全性の低いアプリのアクセス」を有効にする
Flask-LDAPConn
ユーザのモデルクラスを作成するだけで、アクセスできるようになるので非常に便利です。
code: python
import flask
from ldap3 import SUBTREE, STRING_TYPES
from ldap3.core.exceptions import LDAPAttributeError, LDAPStartTLSError
from flask_login import UserMixin
from flask_ldapconn import LDAPConn
from flask_ldapconn.entry import LDAPEntry
from flask_ldapconn.attribute import LdapField
TESTING = True
USERID='test001'
USER_EMAIL = 'iisaka51@gmail.com'
USER_PASSWORD = ''
LDAP_SERVER = 'LDAPサーバのアドレス'
LDAP_BINDDN = None
LDAP_SECRET = None
LDAP_BASEDN = 'cn=admin,dc=sampleldap,dc=com'
LDAP_SEARCH_ATTR = 'mail'
LDAP_SEARCH_FILTER = '(mail=%s)' % USER_EMAIL
LDAP_QUERY_FILTER = 'email: %s' % USER_EMAIL
LDAP_USE_TLS=False
class User(LDAPEntry, UserMixin):
# LDAP meta-data
# inetOrgPerson
name = LdapField('cn')
email = LdapField('mail')
title = LdapField('title')
userid = LdapField('uid')
surname = LdapField('sn')
givenname = LdapField('givenName')
def get_id(self):
return self.userid
class Account(User):
# LDAP meta-data
# posixAccount
uidnumber = LdapField('uidNumber')
gidnumber = LdapField('gidNumber')
shell = LdapField('loginShell')
homedir = LdapField('homeDirectory')
password = LdapField('userPassword')
app = flask.Flask(__name__)
app.config.from_object(__name__)
ldap = LDAPConn(app)
with app.test_request_context():
ldapc = ldap.connection
SUBTREE, attributes=attr) result = ldapc.result
response = ldapc.response
print(response)
user = Account.query.filter(f"userid: {USERID}").first()
print(f'userid: {user.userid} email={user.email} homedir={user.homedir}')
Flask-loguru
FlaskのログがJSON形式で出力されるようになり、パーサーを書かなくても Pandas などで簡単に読み込んで集計することができるので便利です。
code: python
from flask import Flask
from flask_loguru import Logger
LOG_PATH='/home/work/www/log'
LOG_NAME='run.log'
app = Flask(__name__)
app.config.from_object(__name__)
logger = Logger()
使用方法は簡単でLogger() で生成したインスタンスオブジェクト logger にアクセスするか、
あるいは from flask_loguru import logger で取得した logger オブジェクトにアクセスするだけです。
後者の方法は blueprint などを使ってファイル分割しているFlaskアプリケーションでは記述が簡単になるので便利です。
code: pythonk
from flask_loguru import logger
logger.critical("Critical Hello world")
logger.error("Fail Hello world")
logger.warning("Warning Hello world")
logger.info("Info Hello world")
logger.debug("Debug Hello world")
Flask-IpBan
Flask で特定のIPアドレスからのアクセスを拒否したいときや、指定したURLへのアクセスがあるときに拒絶したいときがあります。
例えば、次のようなURLを送り込んでくる、バックドア攻撃があります。
アプリケーションがこうしたURLをサポートしていないのであれば、
当然拒否するべきですし、該当するIPアドレスはブラックリストに登録して以後のアクセスに制限をかけたくなります。
AbuseIPDB などのサイトでは、報告された悪意のあるIPアドレスをデータベースとして公開しています。 Flask-IpBan はあらかじめ登録したURLやIPアドレスを拒否したり、ホワイトリストとして許可するようにしたりすることができます。 ENGINX、Apache, Gunicorn などで特定のIPアドレスやURLを拒絶する方法もありますが、
アプリケーションとして応答させたいときなどではFlask側で処理させた方が画面のLook&Feel の一貫性を保たせることが簡単になります。
code: python
from flask import Flask
from flask_ipban import IpBan
app = Flask(__name__)
ip_ban = IpBan(app)
ip_ban.load_nuisances(file_name='nuisances.yaml')
ip_ban.ip_whitelist_add('127.0.0.1')
こうすることで、アプリケーションのディレクトリにある nuisances.yaml を読み込んで、ブラックリストに登録してくれます。
code: nuisaces.yaml
regex:
# php, java, .net .etc. .etc. .etc. extensions should not be handled by flask
- .*\.action$
- .*\.asp$
- .*\.aspx$
- .*\.asx$
- .*\.bak$
- .*\.cfm$
(中略)
string:
# all of these are hacking attempts by vulnerability scanners
- /boafrm/formSysCmd
- /_asterisk/
- /admin/assets/js/views/login.js
(中略)
ip:
- 185.39.11.105
IpBan() には次の引数を与えることができます。
app: Flask の アプリケーションインスタンス。init_app() を実行するときは諸略可。
ban_count: この回数に達するまでは観察するだけで拒否はしない。デフォルト10.
ban_seconds: この秒数だけ拒否をする。0では回復しない。
persist: 拒否した記録情報を record_dir に保存する
record_dir: 拒否した記録情報を保存するディレクトリ。デフォルト:/tmp/flask-ip-ban
ipc: True を当てると複数のアプリケーション間で拒否情報を共有する。デフォルトは False.
secret_key: ipc を True にしたときはシークレットキーを同じ値にする必要がある。
デフォルトは Flask の SECRET_KEY。
ip_header: docker, kube hostedenv のプロキシ背後で使用するIPを含むリクエストヘッダーの名前
abuse_IPDB_config: AbuseIPDB.com にアカウントがあるときのアクセスするための情報
{key=アクセスキー, report=False, load=False}
プログラム中でブロックさせる場合は次のようになります。
code: python
from flask import Flask
from flask_ipban import IpBan
app = Flask(__name__)
ip_ban = IpBan(app)
def login:
# ....
# increment block if wrong passwords to prevent password stuffing
# ....
if request.method == 'POST':
if request.arg.get('password') != 'secret':
ip_ban.add()
ip_ban.add() を使うと ban_count だけ様子をみます。
次回のアクセスから拒否させる場合は ip_ban.block() を使います。