Django用户认证(四)自定义认证Customizing authentication
原文:https://www.cnblogs.com/linxiyue/p/4061044.html
扩展已有的用户模型Extending the existing User model
有两种方法来扩展默认的User Model而不用重写自己的模型。如果你不需要改变存储在数据库中的字段,而只是需要改变Model的行为,您可以创建一个基于User的代理Model。允许的行为包括默认的ordering,custom managers, 或者 custom model methods。
如果你想存储与User有关的信息,可以使用一个OneToOneField字段关联到一个存储额外信息的Model。这一Model通常被称为一个profile model模型,它可以用来存储一些非验证所需的信息。例如,你可以创建一个Model:
1
2
3
4
5
|
from django.contrib.auth.models import User class Employee(models.Model): user = models.OneToOneField(User) department = models.CharField(max_length = 100 ) |
访问:
1
2
|
>>> u = User.objects.get(username = 'fsmith' ) >>> freds_department = u.employee.department |
如果需要将profile model的字段添加到admin管理界面的user页面上,需要在应用app的admin.py中定义InlineModelAdmin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User from my_user_profile_app.models import Employee # Define an inline admin descriptor for Employee model # which acts a bit like a singleton class EmployeeInline(admin.StackedInline): model = Employee can_delete = False verbose_name_plural = 'employee' # Define a new User admin class UserAdmin(UserAdmin): inlines = (EmployeeInline, ) # Re-register UserAdmin admin.site.unregister(User) admin.site.register(User, UserAdmin) |
这些profile models并不特别,只是与User Model有一个OneToOne链接。所以当一个user实例创建时,profile model并不会自动创建。
重写User模型Substituting a custom User model
有时候User Model并不适合你的网站,比如你要将email而不是username作为认证标识,这时候就需要重写User Model。
首先,需要将settings中的默认User Model覆盖:
1
|
AUTH_USER_MODEL = 'myapp.MyUser' |
引用Referencing the User model
如果AUTH_USER_MODEL已被重设,那当User Model通过ForeignKey或者ManyToManyField访问时,不能直接访问,而是要通过AUTH_USER_MODEL来访问:
1
2
3
4
5
|
from django.conf import settings from django.db import models class Article(models.Model): author = models.ForeignKey(settings.AUTH_USER_MODEL) |
指定Specifying a custom User model
最简单的定制一个User Model的方法是继承用户类AbstractBaseUser。
源码:
一些关键的字段和方法:
USERNAME_FIELD
必需的。设置认证标识。设置成标识的字段unique必须为True。
1
2
3
4
|
class MyUser(AbstractBaseUser): identifier = models.CharField(max_length = 40 , unique = True ) ... USERNAME_FIELD = 'identifier' |
上面的例子中identifier即作为MyUser的认证标识。
REQUIRED_FIELDS
字段name组成的列表。当创建superuser时用到的字段。
1
2
3
4
5
6
|
class MyUser(AbstractBaseUser): ... date_of_birth = models.DateField() height = models.FloatField() ... REQUIRED_FIELDS = [ 'date_of_birth' , 'height' ] |
列表中不应该包含USERNAME_FIELD字段和password字段。
is_active
AbstractBaseUser默认为True。
get_full_name()
get_short_name()
AbstractBaseUser的子类必须定义的两个方法。
下面为一些AbstractBaseUser的子类可以使用的方法:
get_username()
返回USERNAME_FIELD的值.
is_anonymous()
返回False。
is_authenticated()
返回True。检查一个user是否已登录。
set_password(raw_password)
设置密码
check_password(raw_password)
检查密码是否正确
set_unusable_password()
设置user无密码
has_usable_password()
Returns False if set_unusable_password() has been called for this user.
get_session_auth_hash()
返回密码字段的HMAC. Used for Session invalidation on password change.
还需要为自己的User Model定义一个custom manager。
class models.CustomUserManager
create_user(*username_field*, password=None, **other_fields)
接受username field和required字段来创建用户。例如,如果使用email作为username field, date_of_birth作为required field:
1
2
3
|
def create_user( self , email, date_of_birth, password = None ): # create user here ... |
create_superuser(*username_field*, password, **other_fields)
创建superuser
1
2
3
|
def create_superuser( self , email, date_of_birth, password): # create superuser here ... |
create_superuser中的password是必需的。
扩展内置的表单Custom users and the built-in auth forms
UserCreationForm
依赖于User Model. 扩展User时必须重写。
UserChangeForm
依赖于User Model. 扩展User时必须重写。
AuthenticationForm
Works with任何AbstractBaseUser子类 ,and will adapt to use the field defined in USERNAME_FIELD.
PasswordResetForm
Assumes that the user model has an integer primary key, has a field named email that can be used to identify the user, and a boolean field named is_active to prevent password resets for inactive users.
SetPasswordForm
Works with 任何AbstractBaseUser子类
PasswordChangeForm
Works with任何AbstractBaseUser子类
AdminPasswordChangeForm
Works with任何AbstractBaseUser子类。
定制admin功能Custom users and Admin
如果想自己定义的User Model能与admin管理系统一起使用,还需要定义一些字段和方法。
is_staff
是否允许user访问admin界面
is_active
用户是否活跃。
has_perm(perm, obj=None):
user是否拥有perm权限。
has_module_perms(app_label):
user是否拥有app中的权限
定制用户和权限Custom users and permissions
如果要定制User的权限系统,最简单的方法是继承PermissionsMixin
源码:
Django内置的User对象就继承了AbstractBaseUser和PermissionsMixin。
源码:
现在可以看一个完整的自定义User Model例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
from django.db import models from django.contrib.auth.models import ( BaseUserManager, AbstractBaseUser ) class MyUserManager(BaseUserManager): def create_user( self , email, date_of_birth, password = None ): """ Creates and saves a User with the given email, date of birth and password. """ if not email: raise ValueError( 'Users must have an email address' ) user = self .model( email = self .normalize_email(email), date_of_birth = date_of_birth, ) user.set_password(password) user.save(using = self ._db) return user def create_superuser( self , email, date_of_birth, password): """ Creates and saves a superuser with the given email, date of birth and password. """ user = self .create_user(email, password = password, date_of_birth = date_of_birth ) user.is_admin = True user.save(using = self ._db) return user class MyUser(AbstractBaseUser): email = models.EmailField( verbose_name = 'email address' , max_length = 255 , unique = True , ) date_of_birth = models.DateField() is_active = models.BooleanField(default = True ) is_admin = models.BooleanField(default = False ) objects = MyUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = [ 'date_of_birth' ] def get_full_name( self ): # The user is identified by their email address return self .email def get_short_name( self ): # The user is identified by their email address return self .email def __str__( self ): # __unicode__ on Python 2 return self .email def has_perm( self , perm, obj = None ): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms( self , app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True @property def is_staff( self ): "Is the user a member of staff?" # Simplest possible answer: All admins are staff return self .is_admin |
可以看到manager定义了create_user()和create_superuser()方法,MyUser定义了USERNAME_FIELD,REQUIRED_FIELDS字段和get_full_name(),get_short_name()方法,为了能与admin一起使用,还定义了is_active,is_staff,has_perm(),has_module_perms()
要在admin中注册自定义的MyUser,还需要在app的admin.py中重写UserCreationForm和UserChangeForm:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
from django import forms from django.contrib import admin from django.contrib.auth.models import Group from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import ReadOnlyPasswordHashField from customauth.models import MyUser class UserCreationForm(forms.ModelForm): """A form for creating new users. Includes all the required fields, plus a repeated password.""" password1 = forms.CharField(label = 'Password' , widget = forms.PasswordInput) password2 = forms.CharField(label = 'Password confirmation' , widget = forms.PasswordInput) class Meta: model = MyUser fields = ( 'email' , 'date_of_birth' ) def clean_password2( self ): # Check that the two password entries match password1 = self .cleaned_data.get( "password1" ) password2 = self .cleaned_data.get( "password2" ) if password1 and password2 and password1 ! = password2: raise forms.ValidationError( "Passwords don't match" ) return password2 def save( self , commit = True ): # Save the provided password in hashed format user = super (UserCreationForm, self ).save(commit = False ) user.set_password( self .cleaned_data[ "password1" ]) if commit: user.save() return user class UserChangeForm(forms.ModelForm): """A form for updating users. Includes all the fields on the user, but replaces the password field with admin's password hash display field. """ password = ReadOnlyPasswordHashField() class Meta: model = MyUser fields = ( 'email' , 'password' , 'date_of_birth' , 'is_active' , 'is_admin' ) def clean_password( self ): # Regardless of what the user provides, return the initial value. # This is done here, rather than on the field, because the # field does not have access to the initial value return self .initial[ "password" ] class MyUserAdmin(UserAdmin): # The forms to add and change user instances form = UserChangeForm add_form = UserCreationForm # The fields to be used in displaying the User model. # These override the definitions on the base UserAdmin # that reference specific fields on auth.User. list_display = ( 'email' , 'date_of_birth' , 'is_admin' ) list_filter = ( 'is_admin' ,) fieldsets = ( ( None , { 'fields' : ( 'email' , 'password' )}), ( 'Personal info' , { 'fields' : ( 'date_of_birth' ,)}), ( 'Permissions' , { 'fields' : ( 'is_admin' ,)}), ) # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin # overrides get_fieldsets to use this attribute when creating a user. add_fieldsets = ( ( None , { 'classes' : ( 'wide' ,), 'fields' : ( 'email' , 'date_of_birth' , 'password1' , 'password2' )} ), ) search_fields = ( 'email' ,) ordering = ( 'email' ,) filter_horizontal = () # Now register the new UserAdmin... admin.site.register(MyUser, MyUserAdmin) # ... and, since we're not using Django's built-in permissions, # unregister the Group model from admin. admin.site.unregister(Group) |
最后,别忘了在settings.py中定义AUTH_USER_MODEL:
1
|
AUTH_USER_MODEL = 'customauth.MyUser' |
Django用户认证(四)自定义认证Customizing authentication的更多相关文章
- Django(62)自定义认证类
前言 如果我们不用使用drf那套认证规则,我们想自定义认证类,那么我们首先要知道,drf本身是如何定义认证规则的,也就是要查看它的源码是如何写的 源码分析 源码的入口在APIView.py文件下的di ...
- DRF认证、自定义认证和权限、自定义权限
源码分析 """ 1)APIView的dispath(self, request, *args, **kwargs) 2)dispath方法内 self.initial( ...
- django用户认证系统——自定义认证后台8
Django auth 应用默认支持用户名(username)进行登录.但是在实践中,网站可能还需要邮箱.手机号.身份证号等进行登录,这就需要我们自己写一个认证后台,用于验证用户输入的用户信息是否正确 ...
- drf框架中jwt认证,以及自定义jwt认证
0909自我总结 drf框架中jwt 一.模块的安装 官方:http://getblimp.github.io/django-rest-framework-jwt/ 他是个第三方的开源项目 安装:pi ...
- Django认证系统auth认证
使用Django认证系统auth认证 auth认证系统可以处理范围非常广泛的任务,且具有一套细致的密码和权限实现.对于需要与默认配置不同需求的项目,Django支持扩展和自定义认证;会将用户信息写入到 ...
- 跟我一起学Go系列:Go gRPC 安全认证方式-Token和自定义认证
Go gRPC 系列: 跟我一起学Go系列:gRPC安全认证机制-SSL/TLS认证 跟我一起学 Go 系列:gRPC 拦截器使用 跟我一起学 Go 系列:gRPC 入门必备 接上一篇继续讲 gRPC ...
- ocelot 自定义认证和授权
ocelot 自定义认证和授权 Intro 最近又重新启动了网关项目,服务越来越多,每个服务都有一个地址,这无论是对于前端还是后端开发调试都是比较麻烦的,前端需要定义很多 baseUrl,而后端需要没 ...
- .Net Core中自定义认证实现
一.起因 最近项目中需要对项目同时支持JWT认证,以及自定义的认证校验方式认证.通过对官方文档了解,得到认证实现主要通过继承IAuthenticationHandler 或 Authenticatio ...
- Django的用户认证组件,自定义分页
一.用户认证组件 1.auth模块 from django.conrtrib import auth django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: 1)authen ...
- django用户认证系统——拓展 User 模型
Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息.对于 Django 内置的 User 模型, 仅包含以下一些主要的属性: username,即用户名 ...
随机推荐
- SEO 爬虫原理介绍
一篇关于网络爬虫程序的一些原理及体系结构纯技术文章,一些地方可能不会看的非常明确.对于SEO行业,常常和搜索引擎及其爬虫程序打交道,细致浏览下,一些不清楚而自己又非常想了解的地方,能够借助搜索来需找相 ...
- leetcode第一刷_Minimum Depth of Binary Tree
非常easy的题目.只是还是认为要说一下. 最小深度.非常快想到bfs,层序遍历嘛.本科的时候实在是没写过多少代码,一開始竟然想不到怎么保存一层的信息.后来想到能够压入一个特殊的对象,每次到达这个对象 ...
- MVC地区多级联动扩展实现(非递归形式)
MVC前台界面调用方式如下: @Html.AreaDropDownList(, string.Empty) 参数说明: 第一个参数控件的名称: 第二个参数选中的地区编码: 第三个参数地区层级: 第四个 ...
- bzoj-3524 Couriers
题意: 给出一个长度为n的序列和m次询问. 每次询问给出区间[l,r],求区间中出现次数大于(r-l+1)/2的数字. n.m<=500000.1<=每一个数字<=n: 题解: 主席 ...
- DeepLearning to digit recognizer in kaggle
DeepLearning to digit recongnizer in kaggle 近期在看deeplearning,于是就找了kaggle上字符识别进行练习.这里我主要用两种工具箱进行求解.并比 ...
- JS垃圾回收——和其他语言一样,JavaScript 的 GC 策略也无法避免一个问题:GC 时,停止响应其他操作,这是为了安全考虑
JavaScript 内存管理 & 垃圾回收机制 标记清除 js 中最常用的垃圾回收方式就是标记清除.当变量进入环境时,例如,在函数中声明一个变量,就将这个而变量标记为“进入环境”.从逻辑上讲 ...
- [MVC.NET] Asp.Net MVC3 简单入门第一季
转自:http://www.cnblogs.com/fly_dragon/archive/2011/10/12/2208042.html 初识Asp.Net MVC2.0 初识Asp.Net MVC2 ...
- python里使用reduce()函数
reduce()函数在库functools里,如果要使用它,要从这个库里导入.reduce函数与map函数有不一样地方,map操作是并行操作,reduce函数是把多个参数合并的操作,也就是从多个条件简 ...
- IE之css3效果兼容
一.兼容css阴影效果(ie滤镜) 1.Shadow,阴影 .shadow { -moz-box-shadow: 3px 3px 4px #000; -webkit-box-shadow: 3px 3 ...
- [Offer收割]编程练习赛38
漏写的数字 #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #inclu ...