flaskのソースコードを読んでいく(1)

以下のソースコードを読んでいきました。

https://github.com/pallets/flask/blob/master/src/flask/sessions.py

```python
# -*- coding: utf-8 -*-
```

最初はこのコードから始まります。Pythonの教科書などで冒頭に書けと言われているやつですね。

```python
"""
    flask.sessions
    ~~~~~~~~~~~~~~
    Implements cookie based sessions based on itsdangerous.
    :copyright: 2010 Pallets
    :license: BSD-3-Clause
"""
```

sessonの内容を記述するコードのようです。itsdangerousというパッケージがあるようで、以下のリンクに説明が書いてあるようです。itsdangerousを使って、cookieベースのセッションを実装しているようです。

https://pythonhosted.org/itsdangerous/

ここではitsdangerousのBadSignatureとURLSafeTimedSerializerがインポートされてます。

```python
from itsdangerous import BadSignature
from itsdangerous import URLSafeTimedSerializer
```

itsdangerousについては、以下のようなコードが例として示されています。

```Python
from itsdangerous import Signer
s = Signer('secret-key')
s.sign('my string')
```
'my string.wh6tMHxLgJqB6oY1uT73iMlyrOA'

以下のコードでサインを確認できます。

```Python
s.unsign('my string.wh6tMHxLgJqB6oY1uT73iMlyrOA')
```
'my string'

さて、'my string.wh6tMHxLgJqB6oY1uT73iMlyrOA'の最後のAをOに変えてみたらどうでしょうか？

```Python
s.unsign('my string.wh6tMHxLgJqB6oY1uT73iMlyrOO')
```
以下のような出力になります。

```
BadSignatureTraceback (most recent call last)
<ipython-input-23-8d912c717760> in <module>()
----> 1 s.unsign('my string.wh6tMHxLgJqB6oY1uT73iMlyrOO')

/usr/local/lib/python2.7/dist-packages/itsdangerous/signer.pyc in unsign(self, signed_value)
    167         if self.verify_signature(value, sig):
    168             return value
--> 169         raise BadSignature("Signature %r does not match" % sig, payload=value)
    170 
    171     def validate(self, signed_value):

BadSignature: Signature 'wh6tMHxLgJqB6oY1uT73iMlyrOO' does not match
```

ここで、インポートされていた別のモジュールのBadSignature例外が現れましたね。
では、以下のようにしてみます。

```Python
try:
    s.unsign('my string.wh6tMHxLgJqB6oY1uT73iMlyrOO')
except BadSignature:
    print("BadSignature Occurres!!")
```
"BadSignature Occurres!!"

見事にキャッチしてくれましたね。このようなBadSignature例外のキャッチのためにBadSignatureのインポートが必要なのです。

URLSafeSerializerについては、以下のようなエグザンプルコードがありました。シークレットキーによって、データに対して、署名をしてくれるようです。

```python
>>> from itsdangerous import URLSafeSerializer
>>> s = URLSafeSerializer('secret-key')
>>> s.dumps([1, 2, 3, 4])
'WzEsMiwzLDRd.wSPHqC0gR7VUqivlSukJ0IeTDgo'
>>> s.loads('WzEsMiwzLDRd.wSPHqC0gR7VUqivlSukJ0IeTDgo')
[1, 2, 3, 4]
```

ところで、違ったシークレットキーでデコードしてみたらどうなるんでしょうか？

```python
from itsdangerous import URLSafeSerializer
s = URLSafeSerializer('secret-key')
s2 = URLSafeSerializer('secret-key2')
s2.loads(s.dumps([1, 2, 3, 4]))
```
BadSignatureエラーが生成されます。

```
BadSignatureTraceback (most recent call last)
<ipython-input-27-0276404e6c12> in <module>()
      2 s = URLSafeSerializer('secret-key')
      3 s2 = URLSafeSerializer('secret-key2')
----> 4 s2.loads(s.dumps([1, 2, 3, 4]))

/usr/local/lib/python2.7/dist-packages/itsdangerous/serializer.pyc in loads(self, s, salt)
    187             except BadSignature as err:
    188                 last_exception = err
--> 189         raise last_exception
    190 
    191     def load(self, f, salt=None):

BadSignature: Signature 'wSPHqC0gR7VUqivlSukJ0IeTDgo' does not match
```

つまるところ、BadSignatureとは、署名が一致しなかった時に生成される例外のようです。つまるところ、itsdangerousとは、署名をマネージしてくれるフレームワークということになります。信頼できない場所で、メッセージのやりとりをするWebなどでは、必須の機能になりますね。
この記事を書くために、Google Collaboratoryを使いました。