summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorJoseph Kocherhans <joseph@jkocherhans.com>2006-05-10 04:39:34 +0000
committerJoseph Kocherhans <joseph@jkocherhans.com>2006-05-10 04:39:34 +0000
commitb15b11f5b79a4bfce73e82ea7cdb0b3a0652c9cc (patch)
tree5546a35d7a7cbe9c70fbaefb8912d6922905737d /docs
parent4aeb7b02107bdc2842e9e9c82b4f2369cb3ca2bf (diff)
multi-auth: Merged to [2890]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multi-auth@2891 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
-rw-r--r--docs/add_ons.txt10
-rw-r--r--docs/authentication.txt74
-rw-r--r--docs/csrf.txt68
-rw-r--r--docs/db-api.txt2
-rw-r--r--docs/generic_views.txt2
-rw-r--r--docs/model-api.txt18
-rw-r--r--docs/modpython.txt4
-rw-r--r--docs/overview.txt17
-rw-r--r--docs/request_response.txt2
-rw-r--r--docs/tutorial01.txt2
10 files changed, 171 insertions, 28 deletions
diff --git a/docs/add_ons.txt b/docs/add_ons.txt
index e602e429ad..28df4f55b6 100644
--- a/docs/add_ons.txt
+++ b/docs/add_ons.txt
@@ -57,6 +57,16 @@ See the `syndication documentation`_.
.. _syndication documentation: http://www.djangoproject.com/documentation/syndication/
+csrf
+====
+
+A middleware for preventing Cross Site Request Forgeries
+
+See the `csrf documentation`_.
+
+.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/
+
+
Other add-ons
=============
diff --git a/docs/authentication.txt b/docs/authentication.txt
index 0b7094188d..3604fe7360 100644
--- a/docs/authentication.txt
+++ b/docs/authentication.txt
@@ -267,17 +267,25 @@ previous section). You can tell them apart with ``is_anonymous()``, like so::
How to log a user in
--------------------
-To log a user in, do the following within a view::
+Depending on your task, you'll probably want to make sure to validate the
+user's username and password before you log them in. The easiest way to do so
+is to use the built-in ``authenticate`` and ``login`` functions from within a
+view::
- from django.contrib.auth.models import SESSION_KEY
- request.session[SESSION_KEY] = some_user.id
+ from django.contrib.auth import authenticate, login
+ username = request.POST['username']
+ password = request.POST['password']
+ user = authenticate(username=username, password=password)
+ if user is not None:
+ login(request, user)
-Because this uses sessions, you'll need to make sure you have
-``SessionMiddleware`` enabled. See the `session documentation`_ for more
-information.
+``authenticate`` checks the username and password. If they are valid it
+returns a user object, otherwise it returns ``None``. ``login`` makes it so
+your users don't have send a username and password for every request. Because
+the ``login`` function uses sessions, you'll need to make sure you have
+``SessionMiddleware`` enabled. See the `session documentation`_ for
+more information.
-This assumes ``some_user`` is your ``User`` instance. Depending on your task,
-you'll probably want to make sure to validate the user's username and password.
Limiting access to logged-in users
----------------------------------
@@ -611,3 +619,53 @@ Finally, note that this messages framework only works with users in the user
database. To send messages to anonymous users, use the `session framework`_.
.. _session framework: http://www.djangoproject.com/documentation/sessions/
+
+Other Authentication Sources
+============================
+
+Django supports other authentication sources as well. You can even use
+multiple sources at the same time.
+
+Using multiple backends
+-----------------------
+
+The list of backends to use is controlled by the ``AUTHENTICATION_BACKENDS``
+setting. This should be a tuple of python path names. It defaults to
+``('django.contrib.auth.backends.ModelBackend',)``. To add additional backends
+just add them to your settings.py file. Ordering matters, so if the same
+username and password is valid in multiple backends, the first one in the
+list will return a user object, and the remaining ones won't even get a chance.
+
+Writing an authentication backend
+---------------------------------
+
+An authentication backend is a class that implements 2 methods: ``get_user(id)``
+and ``authenticate(**credentials)``. The ``get_user`` method takes an id, which
+could be a username, and database id, whatever, and returns a user object. The
+``authenticate`` method takes credentials as keyword arguments. Many times it
+will just look like this::
+
+ class MyBackend:
+ def authenticate(username=None, password=None):
+ # check the username/password and return a user
+
+but it could also authenticate a token like so::
+
+ class MyBackend:
+ def authenticate(token=None):
+ # check the token and return a user
+
+Regardless, ``authenticate`` should check the credentials it gets, and if they
+are valid, it should return a user object that matches those credentials.
+
+The Django admin system is tightly coupled to the Django User object described
+at the beginning of this document. For now, the best way to deal with this is to
+create a Django User object for each user that exists for your backend (i.e.
+in your ldap directory, your external sql database, etc.) You can either
+write a script to do this in advance, or your ``authenticate`` method can do
+it the first time a user logs in. `django.contrib.auth.backends.SettingsBackend`_
+is an example of the latter approach. Note that you don't have to save a user's
+password in the Django User object. Your backend can still check the password
+against an external source, and return a Django User object.
+
+.. _django.contrib.auth.backends.SettingsBackend: http://code.djangoproject.com/browser/django/branches/magic-removal/django/contrib/auth/backends.py
diff --git a/docs/csrf.txt b/docs/csrf.txt
new file mode 100644
index 0000000000..4ea09552fc
--- /dev/null
+++ b/docs/csrf.txt
@@ -0,0 +1,68 @@
+=====================================
+Cross Site Request Forgery Protection
+=====================================
+
+The CsrfMiddleware class provides easy-to-use protection against
+`Cross Site Request Forgeries`_. This type of attack occurs when a malicious
+web site creates a link or form button that is intended to perform some action
+on your web site, using the credentials of a logged-in user who is tricked
+into clicking on the link in their browser.
+
+The first defense against CSRF attacks is to ensure that GET requests
+are side-effect free. POST requests can then be protected by adding this
+middleware into your list of installed middleware.
+
+
+.. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF
+
+How to use it
+=============
+Add the middleware ``"django.contrib.csrf.middleware.CsrfMiddleware"`` to
+your list of middleware classes, ``MIDDLEWARE_CLASSES``. It needs to process
+the response after the SessionMiddleware, so must come before it in the
+list. It also must process the response before things like compression
+happen to the response, so it must come after GZipMiddleware in the list.
+
+How it works
+============
+CsrfMiddleware does two things:
+
+1. It modifies outgoing requests by adding a hidden form field to all
+ 'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is
+ a hash of the session ID plus a secret. If there is no session ID set,
+ this modification of the response isn't done, so there is very little
+ performance penalty for those requests that don't have a session.
+
+2. On all incoming POST requests that have the session cookie set, it
+ checks that the 'csrfmiddlewaretoken' is present and correct. If it
+ isn't, the user will get a 403 error.
+
+This ensures that only forms that have originated from your web site
+can be used to POST data back.
+
+It deliberately only targets HTTP POST requests (and the corresponding
+POST forms). GET requests ought never to have side effects (if you are
+using HTTP GET and POST correctly), and so a CSRF attack with a GET
+request will always be harmless.
+
+POST requests that are not accompanied by a session cookie are not protected,
+but they do not need to be protected, since the 'attacking' web site
+could make these kind of requests anyway.
+
+The Content-Type is checked before modifying the response, and only
+pages that are served as 'text/html' or 'application/xml+xhtml'
+are modified.
+
+Limitations
+===========
+CsrfMiddleware requires Django's session framework to work. If you have
+a custom authentication system that manually sets cookies and the like,
+it won't help you.
+
+If your app creates HTML pages and forms in some unusual way, (e.g.
+it sends fragments of HTML in javascript document.write statements)
+you might bypass the filter that adds the hidden field to the form,
+in which case form submission will always fail. It may still be possible
+to use the middleware, provided you can find some way to get the
+CSRF token and ensure that is included when your form is submitted.
+
diff --git a/docs/db-api.txt b/docs/db-api.txt
index e3303ea576..0a400b2c93 100644
--- a/docs/db-api.txt
+++ b/docs/db-api.txt
@@ -1070,7 +1070,7 @@ Lookups that span relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Django offers a powerful and intuitive way to "follow" relationships in
-lookups, taking care of the SQL ``JOIN``s for you automatically, behind the
+lookups, taking care of the SQL ``JOIN``\s for you automatically, behind the
scenes. To span a relationship, just use the field name of related fields
across models, separated by double underscores, until you get to the field you
want.
diff --git a/docs/generic_views.txt b/docs/generic_views.txt
index 5d20f2e41b..597ef96104 100644
--- a/docs/generic_views.txt
+++ b/docs/generic_views.txt
@@ -62,6 +62,8 @@ Most generic views require the ``queryset`` key, which is a ``QuerySet``
instance; see the `database API docs`_ for more information about ``Queryset``
objects.
+.. _database API docs: http://www.djangoproject.com/documentation/db_api/
+
"Simple" generic views
======================
diff --git a/docs/model-api.txt b/docs/model-api.txt
index 073a0f3ea9..6d6249ee88 100644
--- a/docs/model-api.txt
+++ b/docs/model-api.txt
@@ -52,7 +52,7 @@ Some technical notes:
* The name of the table, ``myapp_person``, is automatically derived from
some model metadata but can be overridden. See _`Table names` below.
* An ``id`` field is added automatically, but this behavior can be
- overriden. See _`Automatic primary key fields` below.
+ overriden. See `Automatic primary key fields`_ below.
* The ``CREATE TABLE`` SQL in this example is formatted using PostgreSQL
syntax, but it's worth noting Django uses SQL tailored to the database
backend specified in your `settings file`_.
@@ -124,7 +124,7 @@ Here are all available field types:
An ``IntegerField`` that automatically increments according to available IDs.
You usually won't need to use this directly; a primary key field will
automatically be added to your model if you don't specify otherwise. See
-_`Automatic primary key fields`.
+`Automatic primary key fields`_.
``BooleanField``
~~~~~~~~~~~~~~~~
@@ -1111,7 +1111,7 @@ If ``fields`` isn't given, Django will default to displaying each field that
isn't an ``AutoField`` and has ``editable=True``, in a single fieldset, in
the same order as the fields are defined in the model.
-The ``field_options`` dictionary can have the following keys::
+The ``field_options`` dictionary can have the following keys:
``fields``
~~~~~~~~~~
@@ -1312,6 +1312,8 @@ The way ``Manager`` classes work is documented in the `Retrieving objects`_
section of the database API docs, but this section specifically touches on
model options that customize ``Manager`` behavior.
+.. _Retrieving objects: http://www.djangoproject.com/documentation/db_api/#retrieving-objects
+
Manager names
-------------
@@ -1401,17 +1403,17 @@ example, using this model::
...the statement ``Book.objects.all()`` will return all books in the database.
-You can override a ``Manager``'s base ``QuerySet`` by overriding the
+You can override a ``Manager``\'s base ``QuerySet`` by overriding the
``Manager.get_query_set()`` method. ``get_query_set()`` should return a
``QuerySet`` with the properties you require.
-For example, the following model has *two* ``Manager``s -- one that returns
+For example, the following model has *two* ``Manager``\s -- one that returns
all objects, and one that returns only the books by Roald Dahl::
# First, define the Manager subclass.
class DahlBookManager(models.Manager):
def get_query_set(self):
- return super(Manager, self).get_query_set().filter(author='Roald Dahl')
+ return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')
# Then hook it into the Book model explicitly.
class Book(models.Model):
@@ -1442,11 +1444,11 @@ For example::
class MaleManager(models.Manager):
def get_query_set(self):
- return super(Manager, self).get_query_set().filter(sex='M')
+ return super(MaleManager, self).get_query_set().filter(sex='M')
class FemaleManager(models.Manager):
def get_query_set(self):
- return super(Manager, self).get_query_set().filter(sex='F')
+ return super(FemaleManager, self).get_query_set().filter(sex='F')
class Person(models.Model):
first_name = models.CharField(maxlength=50)
diff --git a/docs/modpython.txt b/docs/modpython.txt
index 2b57d0514c..0c0219e2e9 100644
--- a/docs/modpython.txt
+++ b/docs/modpython.txt
@@ -187,8 +187,8 @@ Here are two recommended approaches:
**and** templates -- stay in one place, and you'll still be able to
``svn update`` your code to get the latest admin templates, if they
change.
- 2. Or, copy the admin media files so that they live within your document
- root.
+ 2. Or, copy the admin media files so that they live within your Apache
+ document root.
Error handling
==============
diff --git a/docs/overview.txt b/docs/overview.txt
index 544a897ac6..5a399582e8 100644
--- a/docs/overview.txt
+++ b/docs/overview.txt
@@ -183,7 +183,7 @@ is a simple Python function. Each view gets passed a request object --
which contains request metadata -- and the values captured in the regex.
For example, if a user requested the URL "/articles/2005/05/39323/", Django
-would call the function ``myproject.news.views.article_detail(request,
+would call the function ``mysite.views.article_detail(request,
'2005', '05', '39323')``.
Write your views
@@ -199,7 +199,7 @@ and renders the template with the retrieved data. Here's an example view for
def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
- return render_to_response('news/year_archive.html', {'article_list': a_list})
+ return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list})
This example uses Django's template system, which has several powerful
features but strives to stay simple enough for non-programmers to use.
@@ -219,19 +219,22 @@ might look like::
{% extends "base.html" %}
- {% block title %}{{ article.headline }}{% endblock %}
+ {% block title %}Articles for {{ year }}{% endblock %}
{% block content %}
- <h1>{{ article.headline }}</h1>
- <p>By {{ article.get_reporter.full_name }}</p>
+ <h1>Articles for {{ year }}</h1>
+
+ {% for article in article_list %}
+ <p>{{ article.headline }}</p>
+ <p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
- {{ article.article }}
+ {% endfor %}
{% endblock %}
Variables are surrounded by double-curly braces. ``{{ article.headline }}``
means "Output the value of the article's headline attribute." But dots aren't
used only for attribute lookup: They also can do dictionary-key lookup, index
-lookup and function calls (as is the case with ``article.get_reporter``).
+lookup and function calls.
Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|"
character). This is called a template filter, and it's a way to filter the value
diff --git a/docs/request_response.txt b/docs/request_response.txt
index 6fa4311f61..33e5ef4d84 100644
--- a/docs/request_response.txt
+++ b/docs/request_response.txt
@@ -102,7 +102,7 @@ All attributes except ``session`` should be considered read-only.
``AuthenticationMiddleware`` activated. For more, see
`Authentication in Web requests`_.
- .. Authentication in Web requests: http://www.djangoproject.com/documentation/authentication/#authentication-in-web-requests
+ .. _Authentication in Web requests: http://www.djangoproject.com/documentation/authentication/#authentication-in-web-requests
``session``
A readable-and-writable, dictionary-like object that represents the current
diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt
index 1c3f977d95..03d4eac635 100644
--- a/docs/tutorial01.txt
+++ b/docs/tutorial01.txt
@@ -69,7 +69,7 @@ These files are:
* ``urls.py``: The URL declarations for this Django project; a "table of
contents" of your Django-powered site.
-.. _more on packages: http://docs.python.org/tut/node8.html#packages
+.. _more about packages: http://docs.python.org/tut/node8.html#packages
The development server
----------------------