django 验证和授权
Posted jingxuan-li
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django 验证和授权相关的知识,希望对你有一定的参考价值。
User模型
一、 User模型简介
1. 是验证和授权框架的核心模型,完整路径为:django.contrib.auth.models.User
2. 模型中拥有的字段:
1. username:用户名,max_lenght = 150,不能为空且必须唯一,可以包含字符: _ @ + . -,可以包含数字和英文
2. first_name:外国人的first_name,max_lenght = 150,可以为空
3. last_name:外国人的last_name,max_lenght = 150,可以为空
4. email:邮箱,可以为空
5. password:密码,经过哈希加密后的密码
6. groups:分组,一个用户可以属于多个分组,一个分组可以拥有多个用户
7. user_permissions:权限
8. is_staff:是否可以进入到admin站点,代表是否为员工
9. is_active:是否可用 True/False
10. is_superuser:是否为超级管理员,拥有网站所有权限
11. last_login:上次登录时间
12. date_joined:账号创建时间
二、User模型基本用法(一般会将User模型进行拓展重构,那样不会生成不必要的一些字段):
1. 用户创建(必须传递字段:username,email,password)
·创建普通用户(模型.objects.create_user()):
示例代码:
from django.contrib.auth.models import User # 创建一个普通用户 user = User.objects.create_user(‘lijingxuan‘,‘[email protected]‘,‘123456‘) # 对user对象模型中的字段进行修改 user.last_name=‘jingxuan‘ user.save()
·创建超级用户(模型.objects.create_superuser()):
使用代码创建:
from django.contrib.auth.models import User user = User.objects.create_superuser(‘lijingxuan‘,‘[email protected]‘,‘123456‘)
在终端通过命令行的方式创建:python manage.py createsuperuser
2. 密码修改(对象.set_password()):
示例代码:
from django.contrib.auth.models import User # 获得主键为1的用户数据 user = User.objects.get(pk=1) # 使用set_password()方法将密码加密后,存入数据库 user.set_password(‘新的密码‘) user.save()
3. 登录验证(django.contrib.auth.authenticate):
1. 这个方法只能通过:username 和 password 进行验证,可以通过重构设置 User 模型中 USERNAME_FIELD 字段值来更改
代码示例:
from dango.contrib.auth import authenticate # 如果验证失败将返回None user = authenticate(username=‘lijingxuan‘,password=‘123456‘)
# 默认request=None,在视图中使用时需要传入 #user = authenticate(request,username=‘lijingxuan‘,password=‘123456‘)
if user is not None: # 验证通过 else: # 验证失败
三、User模型的拓展(重点部分):
1. 方法1:设置Proxy模型
采用情况:当对User模型中的字段无须进行修改,只是在此基础上增加一些处理方法,则可采纳
缺点:拓展性差
示例代码:
from django.contrib.auth import User # 定义一个Person继承自User class Person(User): # 在Meta中设置proxy为True,表示这个是User的一个代理模型 class Meta: proxy=True def get_blacklist(self):
# 自定义一个方法,返回没有被拉黑的用户账号信息
# User.objects.all() 与 Person.objects.all() 是等价的,因为他们都从User模型中获取数据 return self.objects.filter(is_active=Flase)
2. 方法2:一对一外键
采用情况:当对验证方法 authenticate 没有其他要求(验证 username 和 password 即可完成),但是有想要增加一些新字段,则可采用
缺点:拓展性一般
代码示例:
from django.contrib.auth.models improt User from django.db improt models # receiver: 新号处理方法,当User模型调用了save方法,那么就会创建一个 UserExtension 对象和 User 进行绑定 from django.dispatch import receiver from django.db.models.signals import post_save # 自动以一个模型 class UserExtension(models.Model): #与 User 模型进行绑定,当User调用save()方法的时候,会发送一个信号,通过receiver来监听 related_name:区别名 user = models.OneToOneField(User,on_delete=models.CASCADE,related_name=‘extension‘) birthday = models.DateField(null=True,blank=True) school = models.CharField(max_length=100) # 信号监听装饰器:监听User模型的save方法,一旦User模型使用save方法则会执行create_user_extension方法 @receiver(post_save,sender=User) def create_user_extension(sender,instance,created,**kwargs): # 创建一个处理方法: # 参数:create:是否为创建,instance:User对象,sender:发送者 if created: # 如果为新创建对象,则创建一个对应的对象 UserExtension.objects.create(user=instance) else:
# 如果为已有的对象,则也保存一下 instance.extension.save()
3. 继承1: AbstractUser:
应用场景:对用户验证 authenticate 不满意,不想要修改 User 模型上的字段但想增加一些字段,那么可以直接继承 django.contrib.auth.models.AbstractUser,这个是 User 模型的父类
缺点:会差生一些不想要的字段
代码示例:
from django.db import models
# from django.contrib.auth.models import User
from django.contrib.auth.models import BaseUserManager,AbstractUser
class UserManager(BaseUserManager):
def _create_user(self,telephone,username,password,**kwargs):
if not telephone:
raise ValueError(‘手机号码不能为空!‘)
if not password:
raise ValueError(‘密码不能为空!‘)
user = self.model(telephone = telephone,username=username,**kwargs)
user.set_password(password)
user.save()
def create_user(self,telephone,username,password,**kwargs):
kwargs[‘is_superuser‘] = False
return self._create_user(telephone,username,password,**kwargs)
def create_superuser(self,telephone,username,password,**kwargs):
kwargs[‘is_superuser‘] = True
return self._create_user(telephone,username,password,**kwargs)
# 继承自AbstractUser,可以添加字段,修改默认验证字段与 objects 的重写
class User(AbstractUser):
telephone = models.CharField(max_length=11,unique=True)
school = models.CharField(max_length=100)
#修改默认验证字段,从 username 修改为 telephone
USERNAME_FIELD = ‘telephone‘
REQUIRED_FIELDS = []
objects = UserManager()
继承2: AbstractBaseUser:
应用场景:修改默认的验证方式,并且对原来 User 模型中的某些字段不想要,那么可以自定义一个模型,然后继承自 AbstractBaseUser,再添加你想要的字段
步骤:
1> 创建模型 和 自定义用户创建方法(Manager):
from django.db import models
# from django.contrib.auth.models import User
from django.contrib.auth.models import BaseUserManager,AbstractUser
# 自定义用户验证方法(objects)
class UserManager(BaseUserManager):
def _create_user(self,telephone,username,password,**kwargs):
if not telephone:
raise ValueError(‘手机号码不能为空!‘)
if not password:
raise ValueError(‘密码不能为空!‘)
user = self.model(telephone = telephone,username=username,**kwargs)
user.set_password(password)
user.save()
def create_user(self,telephone,username,password,**kwargs):
kwargs[‘is_superuser‘] = False
return self._create_user(telephone,username,password,**kwargs)
def create_superuser(self,telephone,username,password,**kwargs):
kwargs[‘is_superuser‘] = True
return self._create_user(telephone,username,password,**kwargs)
class User(AbstractBaseUser,PermissionsMixin): email = models.EmailField(unique=True) username = models.CharField(max_length=150) telephone = models.CharField(max_length=11,unique=True)
# 标识用户是否可用,是否被拉黑 is_active = models.BooleanField(default=True)
# 修改默认验证字段为 telephone
USERNAME_FIELD = ‘telephone‘ # 当通过 createsuperuser 管理命令创建一个用户时的提示,一个列表
REQUIRED_FIELDS = [] # 将 objects 方法执行 UserManager objects = UserManager()
# 获取完整的名称 def get_full_name(self): return self.username
# 获取一个比较简短的用户名 def get_short_name(self): return self.username
2. 在settings中配置 AUTH_USER_MODEL=‘app名称.User‘
3. 使用自定义模型
代码示例:
方法1:
from django.db import models from myauth.models import User class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() # 设置外键 author = models.ForeignKey(User, on_delete=models.CASCADE)
方法2(建议):
from django.db import models from django.conf import settings class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() # 使用 settings 中定义的 AUTH_USER_MODEL 字段来表示,为了更好的使用性 author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
四、权限和分组
1. 登录:django.contrib.auth.login
· 在使用 authenticate 进行验证后,如果通过验证,则会返回一个 user 对象,可以使用 django.contrib.auth.login 进行登录
· 示例代码:
def my_login(request):
if request.method == ‘GET‘
return render(request,‘login.html‘)
else:
# 将post数据放入自定义的表单验证方法:LoginForm 中
form = LoginForm(request.POST)
# 判断表单数据是否验证成功
if form.is_valid():
# 得到表单数据
telephone = form.cleaned_data.get(‘telephone‘)
password = form.cleaned_data.get(‘password‘)
remember = form.cleaned_data.get(‘remember‘)
# 进行表单验证
user = authenticate(request,username=username,password=password) # 判断是否验证成功 if user is not None and user.is_active: # 判断用户是否可用 # 进行登录:将 user 的主键放到 request.session[‘pk‘] 中 login(request,user)
if remember:
# 判断是否需要记住我
# 设置登录过期时间,session.set_expiry(None):表示没有过期时间
request.session.set_expiry(None)
else:
# 设置登录过期时间,session.set_expiry(0):表示当关闭浏览器后,就过期
request.session.set_expiry(0)
# 查找 next 参数内容
next_url = request.GET.get(‘next‘)
if next_url:#如果找到next内容,则重定向到 next 参数代表的页面
return redirect(next_url)
else:
# 如果没有 next 参数,则返回到登录成功后的首页
return HttpResponse(‘登录成功‘)
else:
# 账号或密码错误
else:
# 表单验证失败,登录失败,重定向到 视图
return redirect(reverse(‘视图名称‘))
2. 注销:django.contrib.auth.logout
from django.contrib.auth import logout def my_logout(request):
# 就是把 session 的登录信息清除掉 logout(request) return HttpResponse(‘成功退出登录‘)
3. 登录限制:django.contrib.auth.decorators.login_required
1. 通过一个装饰器进行限制:@login_required()
代码示例:
from django.contrib.auth.decorators import login_requried # 装饰器:当没有登录的情况下访问 my_view,则会重定向到指定的login_url,并且会在 login_url 地址的后面加上一个 next 参数,值为你在未登录前访问的页面,在下次登录时可以直接重定向到 next 所代表的页面 @login_required(login_url=‘/accounts/login/‘) def my_view(request): pass
4. 权限:
以上是关于django 验证和授权的主要内容,如果未能解决你的问题,请参考以下文章
使用 Django GraphQL JWT 和 Graphene Relay 进行身份验证和授权
Django REST Framework - API 身份验证 - 授权应用程序而不是用户