zoukankan      html  css  js  c++  java
  • 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()

     中级大招

    生如逆旅 一苇以航
  • 相关阅读:
    Java并发和高并发学习总结(三)- J.U.C之Atomic包
    Java并发编程和高并发学习总结(二)- Java内存模型
    Java并发编程和高并发学习总结(一)-大纲
    PHP之验证码识别
    python+flask+mongodb+whoosh实现自己的搜索引擎(一):目录
    个性化自己的二维码
    基于bootstrap3的 表格和分页的插件
    构建 shiro struts2 spring3 mybatis 的maven项目
    jsp 嵌套iframe 从iframe中表单提交并传值到外层
    构建 struts2 spring3 mybatis 的maven项目 构建 pom.xml
  • 原文地址:https://www.cnblogs.com/TMMM/p/11993710.html
Copyright © 2011-2022 走看看