diff options
| author | Florian Apolloner <florian@apolloner.eu> | 2020-12-19 14:21:12 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2021-01-06 20:16:47 +0100 |
| commit | 102d92fc09849e1a9004dd3f9a14a0ea9ca392cd (patch) | |
| tree | d1ac6b18640fc755d9248851aba16edb19e2f30e /docs | |
| parent | 5bcba16c0120d4a1bb661f0a495dc47f5ed5465d (diff) | |
Refs #32191 -- Added Signer.sign_object()/unsign_object().
Co-authored-by: Craig Smith <hello@craigiansmith.com.au>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/releases/3.2.txt | 9 | ||||
| -rw-r--r-- | docs/topics/signing.txt | 67 |
2 files changed, 70 insertions, 6 deletions
diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt index aba6a6ccd4..71c5ec09ef 100644 --- a/docs/releases/3.2.txt +++ b/docs/releases/3.2.txt @@ -451,6 +451,15 @@ Security ``SECRET_KEY``, and then going on to access ``settings.SECRET_KEY`` will now raise an :exc:`~django.core.exceptions.ImproperlyConfigured` exception. +* The new ``Signer.sign_object()`` and ``Signer.unsign_object()`` methods allow + signing complex data structures. See :ref:`signing-complex-data` for more + details. + + Also, :func:`signing.dumps() <django.core.signing.dumps>` and + :func:`~django.core.signing.loads` become shortcuts for + :meth:`.TimestampSigner.sign_object` and + :meth:`~.TimestampSigner.unsign_object`. + Serialization ~~~~~~~~~~~~~ diff --git a/docs/topics/signing.txt b/docs/topics/signing.txt index d7d8f42728..2fc49ab747 100644 --- a/docs/topics/signing.txt +++ b/docs/topics/signing.txt @@ -62,6 +62,18 @@ value:: >>> original '2.5' +If you wish to protect a list, tuple, or dictionary you can do so using the +``sign_object()`` and ``unsign_object()`` methods:: + + >>> signed_obj = signer.sign_object({'message': 'Hello!'}) + >>> signed_obj + 'eyJtZXNzYWdlIjoiSGVsbG8hIn0:Xdc-mOFDjs22KsQAqfVfi8PQSPdo3ckWJxPWwQOFhR4' + >>> obj = signer.unsign_object(signed_obj) + >>> obj + {'message': 'Hello!'} + +See :ref:`signing-complex-data` for more details. + If the signature or value have been altered in any way, a ``django.core.signing.BadSignature`` exception will be raised:: @@ -93,6 +105,10 @@ generate signatures. You can use a different secret by passing it to the The ``algorithm`` parameter was added. +.. versionchanged:: 3.2 + + The ``sign_object()`` and ``unsign_object()`` methods were added. + Using the ``salt`` argument --------------------------- @@ -104,11 +120,17 @@ your :setting:`SECRET_KEY`:: >>> signer = Signer() >>> signer.sign('My string') 'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w' + >>> signer.sign_object({'message': 'Hello!'}) + 'eyJtZXNzYWdlIjoiSGVsbG8hIn0:Xdc-mOFDjs22KsQAqfVfi8PQSPdo3ckWJxPWwQOFhR4' >>> signer = Signer(salt='extra') >>> signer.sign('My string') 'My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw' >>> signer.unsign('My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw') 'My string' + >>> signer.sign_object({'message': 'Hello!'}) + 'eyJtZXNzYWdlIjoiSGVsbG8hIn0:-UWSLCE-oUAHzhkHviYz3SOZYBjFKllEOyVZNuUtM-I' + >>> signer.unsign_object('eyJtZXNzYWdlIjoiSGVsbG8hIn0:-UWSLCE-oUAHzhkHviYz3SOZYBjFKllEOyVZNuUtM-I') + {'message': 'Hello!'} Using salt in this way puts the different signatures into different namespaces. A signature that comes from one namespace (a particular salt @@ -121,6 +143,10 @@ different salt. Unlike your :setting:`SECRET_KEY`, your salt argument does not need to stay secret. +.. versionchanged:: 3.2 + + The ``sign_object()`` and ``unsign_object()`` methods were added. + Verifying timestamped values ---------------------------- @@ -156,23 +182,48 @@ created within a specified period of time:: otherwise raises ``SignatureExpired``. The ``max_age`` parameter can accept an integer or a :py:class:`datetime.timedelta` object. + .. method:: sign_object(obj, serializer=JSONSerializer, compress=False) + + .. versionadded:: 3.2 + + Encode, optionally compress, append current timestamp, and sign complex + data structure (e.g. list, tuple, or dictionary). + + .. method:: unsign_object(signed_obj, serializer=JSONSerializer, max_age=None) + + .. versionadded:: 3.2 + + Checks if ``signed_obj`` was signed less than ``max_age`` seconds ago, + otherwise raises ``SignatureExpired``. The ``max_age`` parameter can + accept an integer or a :py:class:`datetime.timedelta` object. + .. versionchanged:: 3.1 The ``algorithm`` parameter was added. +.. _signing-complex-data: + Protecting complex data structures ---------------------------------- If you wish to protect a list, tuple or dictionary you can do so using the -signing module's ``dumps`` and ``loads`` functions. These imitate Python's -pickle module, but use JSON serialization under the hood. JSON ensures that -even if your :setting:`SECRET_KEY` is stolen an attacker will not be able -to execute arbitrary commands by exploiting the pickle format:: +``Signer.sign_object()`` and ``unsign_object()`` methods, or signing module's +``dumps()`` or ``loads()`` functions (which are shortcuts for +``TimestampSigner(salt='django.core.signing').sign_object()/unsign_object()``). +These use JSON serialization under the hood. JSON ensures that even if your +:setting:`SECRET_KEY` is stolen an attacker will not be able to execute +arbitrary commands by exploiting the pickle format:: >>> from django.core import signing - >>> value = signing.dumps({"foo": "bar"}) + >>> signer = signing.TimestampSigner() + >>> value = signer.sign_object({'foo': 'bar'}) + >>> value + 'eyJmb28iOiJiYXIifQ:1kx6R3:D4qGKiptAqo5QW9iv4eNLc6xl4RwiFfes6oOcYhkYnc' + >>> signer.unsign_object(value) + {'foo': 'bar'} + >>> value = signing.dumps({'foo': 'bar'}) >>> value - 'eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI' + 'eyJmb28iOiJiYXIifQ:1kx6Rf:LBB39RQmME-SRvilheUe5EmPYRbuDBgQp2tCAi7KGLk' >>> signing.loads(value) {'foo': 'bar'} @@ -194,3 +245,7 @@ and tuples) if you pass in a tuple, you will get a list from Reverse of ``dumps()``, raises ``BadSignature`` if signature fails. Checks ``max_age`` (in seconds) if given. + +.. versionchanged:: 3.2 + + The ``sign_object()`` and ``unsign_object()`` methods were added. |
