diff options
| author | Joseph Kocherhans <joseph@jkocherhans.com> | 2006-05-10 04:39:34 +0000 |
|---|---|---|
| committer | Joseph Kocherhans <joseph@jkocherhans.com> | 2006-05-10 04:39:34 +0000 |
| commit | b15b11f5b79a4bfce73e82ea7cdb0b3a0652c9cc (patch) | |
| tree | 5546a35d7a7cbe9c70fbaefb8912d6922905737d /docs | |
| parent | 4aeb7b02107bdc2842e9e9c82b4f2369cb3ca2bf (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.txt | 10 | ||||
| -rw-r--r-- | docs/authentication.txt | 74 | ||||
| -rw-r--r-- | docs/csrf.txt | 68 | ||||
| -rw-r--r-- | docs/db-api.txt | 2 | ||||
| -rw-r--r-- | docs/generic_views.txt | 2 | ||||
| -rw-r--r-- | docs/model-api.txt | 18 | ||||
| -rw-r--r-- | docs/modpython.txt | 4 | ||||
| -rw-r--r-- | docs/overview.txt | 17 | ||||
| -rw-r--r-- | docs/request_response.txt | 2 | ||||
| -rw-r--r-- | docs/tutorial01.txt | 2 |
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 ---------------------- |
