django 之(三) --- 认证|权限

用户模块

登陆注册1:Django2.0 

[ 1:N ]

  • user/url.py
1 from django.urls import path
2 from user.views0 import UserTypeView, SingleUserView
3 
4 app_name = 'user'
5 urlpatterns = [
6     # 注意:::此处必须变量名定义名为pk,否则系统识别不到
7     path('singleuser/<int:pk>', SingleUserView.as_view(), name='user-detail'),
8     path('usertype/', UserTypeView.as_view(), name='usertype'),
9 ]
  • user/models.py
 1 from django.db import models
 2 
 3 # 1
 4 class UserType(models.Model):
 5     name = models.CharField(max_length=20, unique=True)
 6     add_time = models.DateTimeField(auto_now=True)
 7 
 8     class Meta:
 9         db_table = 'user_type'
11     def __str__(self):
12         return self.name
13 
14 # n
15 class User(models.Model):
16     username = models.CharField(max_length=20, unique=True)
17     password = models.CharField(max_length=128)
18     phone = models.CharField(max_length=11)
19     add_time = models.DateTimeField(auto_now=True)
20     # related_name='users'的作用是usertype.user_set.all ===> usertype.users.all
21     usertype = models.ForeignKey(to=UserType, on_delete=models.CASCADE, related_name='users', null=True)
22 
23     class Meta:
24         db_table = 'user'
26     def __str__(self):
27         return self.username
  • user/serializers.py 
1 from django.contrib.auth.hashers import make_password
2 from rest_framework import serializers
3 from user.models import User, UserType
 1 class UserSerializerSimple(serializers.ModelSerializer):
 2     repassword = serializers.CharField(max_length=128, write_only=True)
 3 
 4     class Meta:
 5         model = User # 序列化的模型以及字段
 6         fields = ['id', 'username', 'password', 'phone', 'repassword']
 7    # 重写validate类方法。实现密码和确认密码验证
 8     def validate(self, attrs):
 9         if attrs['password'] != attrs['repassword']:
10             raise serializers.ValidationError('两次密码不相等')
11         return attrs
12    # 重写create类方法。实现密码加密功能
13     def create(self, validated_data):
14         username = validated_data['username']
15         password = validated_data['password']
16         phone = validated_data['phone']
17         password = make_password(password) # 密码加密
18         user = User.objects.create(username=username, password=password, phone=phone)
19         return user
 1 # 也可以继承自:serializers.HyperlinkedModelSerializer实现超链接
 2 class UserTypeSerializer(serializers.ModelSerializer):
 3     """
 4     # 1。
 5     # StringRelatedField表示定义序列化的关系模型[两张表的关系定义]。many=True 表示有多个值时需要声明为True。
 6     # users命名要和模型中外键字段定义的related_name='users'中定义的名字一致,且需要添加到下方Meta的fields中
 7     # 最后返回到前端的是对应的从表对象的名称
 8     users = serializers.StringRelatedField(many=True)
 9     # 2。
10     # 也可以使用PrimaryKeyRelatedField。
11     # 最后返回到前端的是对应的从表对象的主键
12     users = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
13     """
14     # 3。
15     # 也可以使用 HyperlinkedRelatedField超链接格式,view_name='user:user-detail'需要定义用户的超链接(url)
16     # 最后返回到前端的是对应的从表对象的链接格式(url)
17     users = serializers.HyperlinkedRelatedField(read_only=True, many=True, view_name='user:user-detail')
18 
19     class Meta:
20         model = UserType
21         fields = '__all__'
22 
23 class SingleUserSerializer(serializers.ModelSerializer):
24     class Meta:
25         model = User
26         fields = ['id', 'username', 'password', 'phone', 'usertype']
27   
1 # 也可以继承自:serializers.HyperlinkedModelSerializer实现超链接
2 class SingleUserSerializer(serializers.ModelSerializer):
3     class Meta:
4         model = User
5         fields = ['id', 'username', 'password', 'phone', 'usertype']
  • user/views.py
 1 from django.http import JsonResponse
 2 from rest_framework.views import APIView
 3 from user.models import User, UserType
 4 from user.serializers import UserTypeSerializer, SingleUserSerializer, 
 5     UserSerializerSimple
 6 
 7 class UserViewsSimple(APIView):
 8     def get(self, request):
 9         pass
10     def post(self, request):
11         user_serializer = UserSerializerSimple(data=request.data)
12         if user_serializer.is_valid():
13             user_serializer.save()
14             return JsonResponse({'status': 200, 'user': user_serializer.data})
 1 class UserTypeView(APIView):
 2     def get(self, request):
 3         usertypes = UserType.objects.all()
 4         """
 5            将从数据库中查询到的数据在UserTypeSerializer中进行序列化。
 6            序列化的是多个值时,需要添加many=True自动将usertypes转为列表类型
 7         """
 8         serializer = UserTypeSerializer(usertypes, many=True, context={'request': request})
 9         data = {
10             'status': 200,
11             'types': serializer.data
12         }
13         return JsonResponse(data)    
1 class SingleUserView(APIView): # 获取单个
2     def get(self, request, pk):
3         user = User.objects.get(pk=pk)
4         serializer = SingleUserSerializer(user, context={'request': request})
5         data = {
6             'status': 200,
7             'types': serializer.data
8         }
9         return JsonResponse(data)

用户模块

    • 用户注册

      • 数据开始:模型,数据库创建用户

        • 用户身份:管理员、普通、删除用户

      • 注册实现

        • 添加了超级管理员生成

    • 用户登陆

      • 验证用户名密码;生成用户令牌

      • 出现登陆和注册的post冲突。添加action

        • path/?action=login

        • path/?action=register

      • 异常捕获尽量精确

    • 用户认证

      • BaseAuthentication

        • authenticate:认证成功会返回一个元组

          • 第一个元素是(user)用户对象

          • 第二个元素是(token或auth)令牌

    • 用户权限

      • BasePermission

        • has_permission:是否具有权限

          • true拥有权限

          • false没有权限

    • 用户认证和权限

      • 直接配置在视图函数上就ok了

 认证权限2:Django1.11

  • settings.py
 1 # 特定超级用户列表
 2 SUPER_USERS = ('GYP', 'LS','ROOT')
 3 
 4 # 缓存书库库
 5 CACHES = {
 6     'default': {
 7         'BACKEND': 'django_redis.cache.RedisCache',
 8         'LOCATION': 'redis://127.0.0.1:6379/1',
 9         'OPTIONS': {
10             'CLIENT_CLASS': 'django_redis.client.DefaultClient',
11         },
12         'TIMEOUT': 60 * 60 *2
13     }
14 }
  • urls.py
 1 # 主url分发
 2 from django.conf.urls import url, include
 3 from django.contrib import admin
 4 
 5 urlpatterns = [
 6     url(r'^admin/', admin.site.urls),
 7     url(r'uauth/',include('UserAuthAndPermission.urls'))
 8 ]
10 # ————————————————————————————------------------------------------------------------#
12 # 子url配置
13 from django.conf.urls import url
14 from UserAuthAndPermission import views
15 
16 # HyperlinkedModelSerializer超链接的序列化需要为超链接配置好一个返回的url的路径url
17 urlpatterns = [
18     # 用户注册登陆路由
19     url(r'^users/$', views.UsersAPIView.as_view()),
20     # name='usermodel-detail'。系统默认的报错配置名字
21     url(r'^users/(?P<pk>d+)/$', views.UserAPIView.as_view(), name='usermodel-detail'),
22 ]
  • UserAuthAndPermission/models.py
1 from django.db import models
2 
3 # 用户模型
4 class UserModel(models.Model):
5     u_name = models.CharField(max_length=32,unique=True)
6     u_password = models.CharField(max_length=256)
7     is_delete = models.BooleanField(default=False)
8     is_super = models.BooleanField(default=False)

  • UserAuthAndPermission/serializers.py
1 from rest_framework import serializers
2 from UserAuthAndPermission.models import UserModel
3 
4 # serializers万能键导入不可用,需要手动导入;HyperlinkedModelSerializer带超链接url的序列化
5 class UserSerializer(serializers.HyperlinkedModelSerializer):
6     class Meta:
7         model = UserModel
8         fields = ('url', 'id', 'u_name', 'u_password', 'is_super')
  • UserAuthAndPermission/constants.py
1 # 自定义常量类
2 HTTP_ACTION_LOGIN = 'login'
4 HTTP_ACTION_REGISTER = 'register'
  • UserAuthAndPermission/auth.py
 1 from django.core.cache import cache
 2 from rest_framework.authentication import BaseAuthentication
 3 from UserAuthAndPermission.models import UserModel
 4 
 5 
 6 # 认证
 7 # 继承自系统类BaseAuthentication。认证用户是否登陆
 8 class UserAuth(BaseAuthentication):
 9     # 实现父类中的抽象方法authenticate,增登陆认证功能。认证成功可返回元组:用户和令牌
10     def authenticate(self, request):
11         if request.method == "GET":
12             token = request.query_params.get('token')
13             try:
14                 u_id = cache.get(token)
15                 user = UserModel.objects.get(pk=u_id)
16                 return user, token
17             except:
18                 return None
  • UserAuthAndPermission/permissions.py
 1 from rest_framework.permissions import BasePermission
 2 from UserAuthAndPermission.models import UserModel
 3 
 4 #  权限。只有登陆认证过,并且是超级管理员用户才可以查询所有
 5 #  继承自BasePermission。进行权限限制判断是否是超级管理员用户
 6 class IsSuperUser(BasePermission):
 7     # 重写has_permission系统方法。
 8     def has_permission(self, request, view):
 9         if request.method == "GET":  # 又有get请求才会去判断权限
10             # 判断是否是模型的实例(判断某个对象是否是某个类的实例)
11             if isinstance(request.user, UserModel):
12                 return request.user.is_super
13             return False
14         return True
  • UserAuthAndPermission/views.py
 1 import uuid
 2 from django.core.cache import cache
 3 from rest_framework import status, exceptions
 4 from rest_framework.generics import ListCreateAPIView
 5 from rest_framework.response import Response
 6 from DjangoREST.settings import SUPER_USERS
 7 from UserAuthAndPermission.auth import UserAuth
 8 from UserAuthAndPermission.constants import HTTP_ACTION_REGISTER, HTTP_ACTION_LOGIN
 9 from UserAuthAndPermission.models import UserModel
10 from UserAuthAndPermission.permissions import IsSuperUser
11 from UserAuthAndPermission.serializers import UserSerializer
12 
13 
14 # 实现所有查询get和创建post功能的类视图继承方式
15 class UsersAPIView(ListCreateAPIView):
16     # 模型序列化,系统默认变量名serializer_class
17     serializer_class = UserSerializer
18     # 从模型中查询获取数据。queryset也是系统默认变量名
19     queryset = UserModel.objects.all()
20     # 认证类。验证用户登陆认证。只有登陆的用户才可以查询
21     authentication_classes = (UserAuth,)
22     # 权限类。验证用户类型权限。只有超级管理员才可以查询
23     permission_classes = (IsSuperUser,)
24 
25     # # get请求。只有是登陆认证认证过的 才可以查询
26     # def get(self, request, *args, **kwargs):
27     #     # 判断是否是模型的实例(判断某个对象是否是某个类的实例)
28     #     if isinstance(request.user, UserModel):
29     #         return self.list(request, *args, **kwargs)
30     #     else:
31     #         raise exceptions.NotAuthenticated
32 
33 
34     # 重写ListCreateAPIView已有的post请求。实现登陆、注册。出现登陆注册公用post问题
35     # 解决:添加action动作(path/?action=login 或者 path/?action=register
36     def post(self, request, *args, **kwargs):
37         # 获取查询参数,相当于django中的额GET方法。
38         action = request.query_params.get('action')
39         # 判断是什么动作
40         if action == HTTP_ACTION_REGISTER:  # 注册
41             return self.create(request, *args, **kwargs)
42         elif action == HTTP_ACTION_LOGIN:  # 登陆
43             u_name = request.data.get('u_name')
44             u_password = request.data.get('u_password')
45 
46             try:
47                 user = UserModel.objects.get(u_name=u_name)
48                 if user.u_password == u_password:
49                     # 登陆成功,给用户一个token令牌存到缓存中
50                     token = uuid.uuid4().hex
51                     cache.set(token, user.id)
52                     data = {
53                         'msg': 'login success',
54                         'status': 200,
55                         'token': token
56                     }
57                     return Response(data)
58                 else:
59                     # 系统系统的状态信息常量类exceptions
60                     raise exceptions.AuthenticationFailed
61             except UserModel.DoesNotExist:  # 异常捕获要精确
62                 raise exceptions.NotFound
63         else:
64             raise exceptions.ValidationError
65 
66     # 重写系统create()方法。指定超级用户的列表在settings.py文件中指定
67     # 超级用户问题实现:只要是在即有特定列表中的用户注册时就自动设为超级用户。
68     def create(self, request, *args, **kwargs):
69         # 源码
70         serializer = self.get_serializer(data=request.data)
71         serializer.is_valid(raise_exception=True)
72         self.perform_create(serializer)
73 
74         data = serializer.data
75         u_name = data.get('u_name')
76         # 判断是否是已有列表中的超级用户
77         if u_name in SUPER_USERS:
78             u_id = data.get('id')
79             user = UserModel.objects.get(pk=u_id)
80             user.is_super = True
81             user.save()
82             # 更新返回信息
83             data.update({'is_super': True})
84         headers = self.get_success_headers(serializer.data)
85         return Response(data, status=status.HTTP_201_CREATED, headers=headers)
86 
87 
88 # 实现单个查询get和创建post功能的类视图继承方式
89 class UserAPIView(ListCreateAPIView):
90     # 模型序列化,系统默认变量名serializer_class
91     serializer_class = UserSerializer
92     # 从模型中查询获取数据。queryset也是系统默认变量名
93     queryset = UserModel.objects.all()

 中级大招

生如逆旅 一苇以航
原文地址:https://www.cnblogs.com/TMMM/p/11993710.html