标签:
Using the Django authentication system
This document explains(解释) the usage(使用) of Django’s authentication system(用户认证系统) in its default configuration(默认配置). This configuration has evolved to serve the most common project needs, handling a reasonably wide range of tasks, and has a careful implementation of passwords and permissions(权限). For projects where authentication needs differ from the default, Django supports extensive
extension and customization of authentication.
这篇文档解释默认配置下Django认证系统的使用。这些配置已经逐步可以满足大部分常见项目的需要,可以处理范围非常广泛的任务,且具有一套细致的密码和权限实现。对于需要与默认配置不同需求的项目,Django支持扩展和自定义认证。
Django authentication provides both authentication(认证) and authorization(授权) together and is generally referred to as the authentication system, as these features are somewhat coupled.
Django的认证同时提供认证和授权,并通常统一称为认证系统,因为这些功能某些地方是耦合的。
User objects
User objects are the core(核心) of the authentication system. They typically represent the people interacting(互动) with your site and are used to enable things like restricting access, registering user profiles(注册用户信息), associating(关联) content with creators etc. Only one class of user exists(存在) in Django’s authentication framework, i.e.,
‘superusers‘ or admin
‘staff‘ users are just user objects with special attributes set, not different classes of user objects.
User对象是认证系统的核心。它们通常表示与你的站点进行交互的用户,并用于启用限制访问、注册用户信息和关联内容给创建者等。在Django的认证框架中只存在一种类型的用户,因此诸如‘superusers‘或管理员‘staff‘用户只是具有特殊属性的user对象,而不是不同类型的user对象。
The primary(主要) attributes of the default user are:
See the
full API documentation for full reference, the documentation that follows is more task oriented(以下的内容更偏重特定的任务).
Creating users
The most direct(直接) way to create users is to use the included
create_user() helper function:
创建users最直接的方法是使用create_user()辅助函数:
>>> from django.contrib.auth.models import User >>> user = User.objects.create_user(‘john‘, ‘lennon@thebeatles.com‘, ‘johnpassword‘) # At this point, user is a User object that has already been saved # to the database. You can continue to change its attributes # if you want to change other fields. >>> user.last_name = ‘Lennon‘ >>> user.save()
Creating superusers
$ python manage.py createsuperuser --username=joe --email=joe@example.com
You will be prompted(提示) for a password. After you enter one, the user will be created immediately. If you leave off(遗漏) the
--username or
--email options, it will prompt you for those values.(将会交互式地提示你输入这些值)
Changing passwords
Django does not store raw (clear text) passwords on the user model, but only a hash (see
documentation of how passwords are managed for full details). Because of this, do not attempt to manipulate(操作) the password attribute of the user directly(直接). This is why a helper function is used when creating a user.
Django不会在user模型上存储原始的(明文)密码,而只是一个哈希(完整的细节参见文档:密码是如何管理的)。因为这个原因,不要尝试直接操作user的password属性。这也是为什么创建一个user时要使用辅助函数。
To change a user’s password, you have several options:
manage.py changepassword *username* offers(提供) a method of changing a User’s password from the command line(命令行). It prompts you to change the password of a given user which you must enter twice. If they both match, the new password will be changed immediately. If you do not supply a user, the command will attempt to change the password whose username matches the current system user.
(注:这种修改方式不用提供原来的密码,但要求密码不少于8位,且有一定的复杂度,不能全为数字)
You can also change a password programmatically(以编程的方式), using
set_password():
>>> from django.contrib.auth.models import User >>> u = User.objects.get(username=‘john‘) >>> u.set_password(‘new password‘) >>> u.save()
(注:可以看出验证系统其实就是一个自带的models,其使用的是该models的特定的方法来进行数据的操作)
Django also provides
views and
forms that may be used to allow users to change their own passwords.(提供了views和forms给用户自己修改密码)
Authenticating users(用户认证)
authenticate(**credentials)[source]
Use
authenticate() to verify a set of credentials(去验证一系列的认证信息). It takes credentials(认证信息) as keyword arguments, username and password for the default case, checks them against each
authentication backend, and returns a
User object if the credentials are valid(有效) for a backend. If the credentials aren’t valid for any backend or if a backend raises
PermissionDenied, it returns None. For example:
认证一个给定验证信息,请使用authenticate()。它以关键字参数形式接收认证信息,在默认的配置下,它是username和password,如果认证通过它将返回一个User对象。如果密码无效或后端触发了
PermissionDenied异常,authenticate()返回None。例子
from django.contrib.auth import authenticate user = authenticate(username=‘john‘, password=‘secret‘) if user is not None: # A backend authenticated the credentials else: # No backend authenticated the credentials
Note
This is a low level(低级别) way to authenticate a set of(一组) credentials; for example, it’s used by the
RemoteUserMiddleware. Unless you are writing your own authentication system(除非你写了自己的一套认证系统), you probably won’t use this(那么你大概不会使用它). Rather if(而如果) you are looking for a way to limit access to logged in users, see the
login_required() decorator.(如果你在寻找一个限制只有登录用户才能访问的方式,可以使用装饰器
login_required())
Permissions and Authorization(权限与授权)
Django comes with(自带) a simple permissions system. It provides a way to assign(分配) permissions to specific users and groups of users(指定的用户和用户组).
django自带了一个简单的权限系统,它提供了为指定的用户和用户组分配权限的方法。
It’s used by the Django admin site, but you’re welcome to use it in your own code.
它已经被Django的admin站点使用,但你也能在你自己的代码中使用。
The Django admin site uses permissions as follows:
django的admin网页使用的权限如下:
- Access to view(查看) the “add” form(表单) and add an object is limited to users with the “add” permission for that type of object.
查看add表单,只有拥有add权限的user类型对象才能添加对象
- Access to view the change list, view the “change” form and change an object is limited to users with the “change” permission for that type of object.
- Access to delete an object is limited to users with the “delete” permission for that type of object.
注:若要添加一个用户,则需要add和change权限,但是change权限实在太危险,甚至能自己变成superuser。
User objects have two many-to-many fields: groups and user_permissions.
User objects can access their related(有关系的) objects in the same way as any other
Django model:
myuser.groups = [group_list] myuser.groups.add(group, group, ...) myuser.groups.remove(group, group, ...) myuser.groups.clear() myuser.user_permissions = [permission_list] myuser.user_permissions.add(permission, permission, ...) myuser.user_permissions.remove(permission, permission, ...) myuser.user_permissions.clear()
Default permissions
When django.contrib.auth is listed in your
INSTALLED_APPS setting, it will ensure that three default permissions – add, change and delete – are created for each Django model defined in one of your installed applications.
当django.contrib.auth在你的INSTALLED_APPS设置中列出时,它将确保为你安装的应用中的每个Django模型创建3个默认的权限 – add、change和delete。
These permissions will be created when you run
manage.py migrate; the first time you run migrate after adding django.contrib.auth to
INSTALLED_APPS, the default permissions will be created for all previously-installed(预先安装的) models, as well as for any new models being installed at that time. Afterward(之后), it will create default permissions for new models each time you run
manage.py migrate (the function that creates permissions is connected to the
post_migrate signal).
这些权限将在你运行manage.py migrate时创建;在添加django.contrib.auth到INSTALLED_APPS中之后,当你第一次运行migrate时,将会为之前安装的模型创建默认的权限,包括与此同时正在安装的新的模型。之后,每当你运行manage.py migrate时,它都将为新的模型创建默认的权限。
(注:即意味着每个models都能add、change、delete数据)
Assuming(假设) you have an application with an
app_label foo and a model named Bar, to test for basic permissions you should use:
- add: user.has_perm(‘foo.add_bar‘)
- change: user.has_perm(‘foo.change_bar‘)
- delete: user.has_perm(‘foo.delete_bar‘)
很少直接访问Permission模型。
############
Model Meta options
Options.app_label
If a model is defined outside of an application in
INSTALLED_APPS, it must declare(声明) which app it belongs to:
如果一个模块在INSTALLED_APPS列表之外的application定义,其必须声明属性那个app
app_label = ‘myapp‘
New in Django 1.9.
If you want to represent(表示) a model with the format app_label.object_name or app_label.model_name you can use model._meta.label or model._meta.label_lower respectively(分别的).
#########
Groups
django.contrib.auth.models.Group models are a generic(通用的) way of categorizing(分类) users so you can apply permissions, or some other label, to those users. A user can belong to any number of groups.
django.contrib.auth.models.Group模型是用户分类的一种通用的方式,通过这种方式你可以应用权限或其它标签到这些用户。一个用户可以属于任意多个组。
A user in a group automatically(自动) has the permissions granted to(授权) that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission.
Beyond permissions, groups are a convenient(方便的) way to categorize(分类) users to give them some label(标签), or extended functionality(拓展功能). For example, you could create a group ‘Special users‘, and you could write code that could, say, give them access to a members-only portion(部分) of your site, or send them members-only email messages.
除权限之外,组还是给用户分类的一种方便的方法以给他们某些标签或扩展的功能。例如,你可以创建一个组‘Special users‘,然后你可以通过代码让他们发言、给他们访问你的站点仅限会员的部分,或者给他们发仅限于会员的邮件。
Programmatically creating permissions(以编程的方式创建权限)
While
custom permissions can be defined within a model’s Meta class, you can also create permissions directly. For example, you can create the can_publish permission for a BlogPost model in myapp:
自定义权限可以在model的Meta中定义,你可以用它直接创建权限。此外,你可以创建can_publish权限给myapp中的 BlogPost model。
from myapp.models import BlogPost from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType content_type = ContentType.objects.get_for_model(BlogPost) permission = Permission.objects.create( codename=‘can_publish‘, name=‘Can Publish Posts‘, content_type=content_type, )
The permission can then be assigned to a
User via its user_permissions attribute or to a
Group via its permissions attribute.
然后该权限可以通过user_permissions属性分配给一个User,或者通过permissions属性分配给Group。
Permission caching(权限的缓存)
The
ModelBackend caches(缓存) permissions on the User object after the first time they need to be fetched(被取来) for a permissions check(权限检查). This is typically fine(典型的做法) for the request-response cycle(循环) since permissions are not typically checked immediately after they are added (in the admin, for example). If you are adding permissions and checking them immediately afterward, in a test or view for example, the easiest solution(最简单的方法) is to re-fetch(再取) the User from the database. For example:
ModelBackend会在第一次检查User对象的权限之后,将结果缓存起来。这对于请求-响应循环还是比较好的(节省资源),在权限添加进来之后并不会立即检查(例如在admin中添加的)。如果你添加了权限并需要立即检查它们,例如在一个测试或视图中,最简单的解决办法是从数据库中重新获取User。 例如:
from django.contrib.auth.models import Permission, User from django.shortcuts import get_object_or_404 def user_gains_perms(request, user_id): user = get_object_or_404(User, pk=user_id) # any permission check will cache the current set of permissions user.has_perm(‘myapp.change_bar‘) permission = Permission.objects.get(codename=‘change_bar‘) user.user_permissions.add(permission) # Checking the cached permission set user.has_perm(‘myapp.change_bar‘) # False # Request new instance of User user = get_object_or_404(User, pk=user_id) # Permission cache is repopulated from the database user.has_perm(‘myapp.change_bar‘) # True ...
Authentication in Web requests
django使用sessions和中间件钩子,将用户验证系统将会处理相应的request。
These provide(提供) a
request.user attribute on every request which represents(代表着) the current user(当前用户). If the current user has not logged in, this attribute will be set to an instance of
AnonymousUser, otherwise it will be an instance of
User.
if request.user.is_authenticated: # Do something for authenticated users. ... else: # Do something for anonymous users. ...
How to log a user in
If you have an authenticated(已验证) user you want to attach to(附属到) the current session - this is done with a
login() function.
To log a user in, from a view, use
login(). It takes an
HttpRequest object and a
User object.
login() saves the user’s ID in the session, using Django’s session framework.
Note that any data set during the anonymous session is retained(保存) in the session after a user logs in.
注意任何在匿名会话中设置的数据都会在用户登入后的会话中都会记住。(也就是说会继承匿名会话时的session。
from django.contrib.auth import authenticate, login def my_view(request): username = request.POST[‘username‘] password = request.POST[‘password‘] user = authenticate(username=username, password=password) if user is not None: login(request, user) # Redirect to a success page. ... else: # Return an ‘invalid login‘ error message. ...
Changed in Django 1.10:
In older versions, when you’re manually(收到) logging a user in, you must successfully authenticate the user with
authenticate() before you call
login(). Now you can set the backend using the new backend argument.
Selecting the authentication backend
When a user logs in, the user’s ID and the backend(后台) that was used for authentication are saved in the user’s session. This allows the same
authentication backend to fetch(获取) the user’s details(细节) on a future(以后的) request. The authentication backend to save in the session is selected as follows:
- Use the value of the optional backend argument, if provided.
- Use the value of the user.backend attribute, if present. This allows pairing(配对) authenticate() and login():authenticate() sets theuser.backend attribute on the User object it returns.
- Use the backend in AUTHENTICATION_BACKENDS, if there is only one.
- Otherwise, raise an exception.
In cases 1 and 2, the value of the backend argument or the user.backend attribute should be a dotted import path string (like that found in
AUTHENTICATION_BACKENDS), not the actual(实际的) backend class.
How to log a user out
from django.contrib.auth import logout def logout_view(request): logout(request) # Redirect to a success page.
Note that
logout() doesn’t throw any errors if the user wasn’t logged in.
若用户没有登录,也不会抛出任何的错误
When you call
logout(), the session data for the current request is completely(完成) cleaned out(清理完). All existing(当前的) data is removed. This is to prevent(防止) another person from using the same Web browser to log in and have access to the previous(先前的) user’s session data. If you want to put anything into the session that will be available(可用) to the user immediately after logging out, do that after calling
django.contrib.auth.logout().(如果还想要设置一些session用于登出右继续使用,请在调用logout之后设置。)
Limiting access to logged-in users(只允许登录用户访问)
The raw way
from django.conf import settings from django.shortcuts import redirect def my_view(request): if not request.user.is_authenticated: return redirect(‘%s?next=%s‘ % (settings.LOGIN_URL, request.path)) # ...
...or display an error message:
from django.shortcuts import render def my_view(request): if not request.user.is_authenticated: return render(request, ‘myapp/login_error.html‘) # ...
The login_required decorator
login_required(redirect_field_name=‘next‘, login_url=None)
[source]¶
from django.contrib.auth.decorators import login_required @login_required def my_view(request): ...
- If the user isn’t logged in, redirect to settings.LOGIN_URL, passing the current absolute path(绝对路径) in the query string. Example:/accounts/login/?next=/polls/3/.
给login的url
- If the user is logged in, execute(执行) the view normally. The view code is free to assume(假设) the user is logged in.
By default, the path that the user should be redirected(重定向) to upon successful authentication is stored in a query string parameter called "next". If you would prefer to(宁愿) use a different name for this parameter(参数),
login_required() takes an optional redirect_field_name parameter:
from django.contrib.auth.decorators import login_required @login_required(redirect_field_name=‘my_redirect_field‘) def my_view(request): ...
Note that if you provide a value to redirect_field_name, you will most likely need to customize(自定义) your login template as well, since the template context variable which stores the redirect path will use the value of redirect_field_name as its key rather than "next" (the default).
注意,如果你提供一个值给redirect_field_name,你非常可能同时需要自定义你的登录模板,因为存储重定向路径的模板上下文变量将使用redirect_field_name值作为它的键,而不是默认的"next"。
from django.contrib.auth.decorators import login_required @login_required(login_url=‘/accounts/login/‘) def my_view(request): ...
Note that if you don’t specify the login_url parameter, you’ll need to ensure that the
settings.LOGIN_URL and your login view are properly associated(适当的关联). For example, using the defaults, add the following lines to your URLconf:
from django.contrib.auth import views as auth_views url(r‘^accounts/login/$‘, auth_views.login),
The
settings.LOGIN_URL also accepts view function names and
named URL patterns. This allows you to freely remap(再映射) your login view within your URLconf without having to update the setting.
Note
The login_required decorator does NOT check the is_active flag on a user, but the default
AUTHENTICATION_BACKENDS reject inactive users(拒绝非活跃的用户).
See also
The LoginRequired mixin
When using
class-based views, you can achieve(取得) the same behavior as with login_required by using the LoginRequiredMixin. This mixin should be at the leftmost(最左边) position(位置) in the inheritance(继承) list.
class LoginRequiredMixin
New in Django 1.9.
If a view is using this mixin, all requests by non-authenticated users will be redirected to the login page or shown an HTTP 403 Forbidden error, depending on the
raise_exception parameter.
You can set any of the parameters of
AccessMixin to customize(自定义) the handling of unauthorized users:
from django.contrib.auth.mixins import LoginRequiredMixin class MyView(LoginRequiredMixin, View): login_url = ‘/login/‘ redirect_field_name = ‘redirect_to‘
Note
Just as the login_required decorator, this mixin does NOT check the is_active flag on a user, but the default
AUTHENTICATION_BACKENDS reject inactive users.
Limiting access to logged-in users that pass a test
To limit access based on certain(某个) permissions or some other test, you’d do essentially(基本上) the same thing as described(描述) in the previous(之前的) section.
The simple way is to run your test on
request.user in the view directly. For example, this view checks to make sure the user has an email in the desired domain(要求的域) and if not, redirects to the login page:
简单的方法就是在视图中直接运行你对request.user的测试。例如,视图检查用户的邮件属于特定的地址(例如@example.com),若不是,则重定向到登录页面。
from django.shortcuts import redirect def my_view(request): if not request.user.email.endswith(‘@example.com‘): return redirect(‘/login/?next=%s‘ % request.path) # ...
user_passes_test(func[, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME])
[source]¶
As a shortcut, you can use the convenient(方便的) user_passes_test decorator which performs(执行) a redirect(重定向) when the callable returns False:
你可以用方便的 user_passes_test 装饰器,当回调函数返回 False 时会执行一个重定向操作:
from django.contrib.auth.decorators import user_passes_test def email_check(user): return user.email.endswith(‘@example.com‘) @user_passes_test(email_check) def my_view(request): ...
user_passes_test() takes a required argument: a callable that takes a
User object and returns True if the user is allowed to view the page. Note that
user_passes_test() does not automatically check that the
User is not anonymous.
user_passes_test() 要求一个以User 对象为参数的回调函数,若用户允许访问此视图,返回 True。注意,user_passes_test() 不会自动检查 User 是否是不是匿名对象。
login_url
Lets you specify the URL that users who don’t pass the test will be redirected to. It may be a login page and defaults to
settings.LOGIN_URL if you don’t specify one.
redirect_field_name
Same as for
login_required(). Setting it to None removes it from the URL, which you may want to do if you are redirecting users that don’t pass the test to a non-login page where there’s no “next page”.
与
login_required()的参数相同。把它设置为 None 来把它从 URL 中移除,当你想把通不过检查的用户重定向到没有next page的非登录页面时。
For example:
@user_passes_test(email_check, login_url=‘/login/‘) def my_view(request): ...
class UserPassesTestMixin
New in Django 1.9.
test_func()
You have to override(重写) the test_func() method of the class to provide the test that is performed(执行). Furthermore(此外), you can set any of the parameters(参数) of
AccessMixin to customize(自定义) the handling of unauthorized(未验证) users:
from django.contrib.auth.mixins import UserPassesTestMixin class MyView(UserPassesTestMixin, View): def test_func(self): return self.request.user.email.endswith(‘@example.com‘)
Using the Django authentication system
标签:
原文地址:http://www.cnblogs.com/pythonxiaohu/p/5790813.html