zoukankan      html  css  js  c++  java
  • python-Django-rest_framework 用户的登录注册及用户认证及权限控制

    models.py

    # models.py
    from django.db import models
    
    class UserModel(models.Model):
    
        u_name = models.CharField(max_length=32, unique=True)  # 用户名唯一
        # 密码需要加密,加密后比较长
        u_password = models.CharField(max_length=256)
        #
        is_delect = models.BooleanField(default=False)
        # 是否是超级管理员
        is_super = models.BooleanField(default=False)

    views.py

    # views.py
    from django.core.cache import cache
    # 创建用户(用户的注册和登录),(超级管理员)查询用户
    
    # 创建用户
    import uuid
    from rest_framework import status, exceptions
    from rest_framework.generics import ListCreateAPIView
    
    # ListCreateAPIView:可以用于用户的创建和查询
    from rest_framework.response import Response
    
    from UserAuth.auth import UserAuth
    from UserAuth.contants import POST_ACTION_REGISTER, POST_ACTION_LOGIN
    from UserAuth.models import UserModel
    from UserAuth.permissions import Userpermission
    from UserAuth.serializers import UserSerializer
    
    # 所有用户
    # ListCreateAPIView中post用于处理用户创建的【Create()】,
    from mydjango.settings import SUPER_USERS
    
    
    class UsersAPIView(ListCreateAPIView):
        # 序列化类
        serializer_class = UserSerializer
        # 查询集和结果集
        queryset = UserModel.objects.all()
        # 用户验证
        authentication_classes = (UserAuth,)
        # 权限控制
        permission_classes = (Userpermission,)
        # 直接进行权限控制permission (如上)
        # 重写get请求,判断request.user 是否是UserModel中的一个实例
        # def get(self, request, *args, **kwargs):
        #     if isinstance(request.user, UserModel):
        #         if request.user.is_super:
        #             return self.list(request, *args, **kwargs)
        #         else:
        #             raise exceptions.NotAuthenticated  # 没有超级管理员的权限
        #     else:
        #         raise exceptions.NotAuthenticated   # 用户没有登录,没有权限访问
    
        # 同一个post做把登录和注册同时完成
        def post(self, request, *args, **kwargs):
            action = request.query_params.get('action')
            # 若参数为register则为注册,创建用户
            if action == POST_ACTION_REGISTER:
                return self.create(request, *args, **kwargs)
            elif action == POST_ACTION_LOGIN:
                # 验证用户名密码
                u_name = request.data.get('u_name')
                u_password = request.data.get('u_password')
                try:
                    user = UserModel.objects.get(u_name=u_name)   # 数据库验证用户名
                    # 用户名存在验证密码
                    if user.u_password == u_password:
                        # 生成令牌,传入客户端和放入服务器缓存或者数据库
                        token = uuid.uuid4().hex
                        # 把token放入缓存,注意Redis在settings中的配置
                        cache.set(token, user.id)
                        # 并传入客户端
                        data = {
                            'msg': 'ok',
                            'status': 200,
                            'token': token
                        }
                        return Response(data)
                    else:
                        raise exceptions.AuthenticationFailed   # 用户密码错误
                except UserModel.DoesNotExist:
                    raise exceptions.NotFound   # 用户名错误
            else:
                raise exceptions.ValidationError  # 验证错误,传入的不是POST请求
    
        # 创建用户
        # 重写的CreateModelMixin中的方法:用于用户的创建
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
    
            data = serializer.data
            u_name = data.get('u_name')
            # 判断是否是创建的超级用户
            if u_name in SUPER_USERS:
                u_id = data.get('id')
                user = UserModel.objects.get(pk=u_id)  # 拿到对应的用户
                user.is_super = True  # 设置为超级用户o0
                user.save()
                data.update({'is_super': True})     # 创建了超级用户,在返回客户端的时候也把对应修改做了
    
            headers = self.get_success_headers(data)
            return Response(data, status=status.HTTP_201_CREATED, headers=headers)
    
    
    # 单个用户,只用于展示
    class UserAPIView(RetrieveAPIView):
        serializer_class = UserSerializer
        queryset = UserModel.objects.all()

    serializers.py

    # serializers.py
    # 用户序列化
    from rest_framework import serializers
    
    from UserAuth.models import UserModel
    
    
    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = UserModel
            # 要显示出来的字段
            fields = ('id', 'u_name', 'u_password', 'is_super')

    contants.py

    # contants.py
    # 只做常量值
    # 这里用作views.py 中action的常量操作
    
    POST_ACTION_LOGIN = 'login'
    POST_ACTION_REGISTER = 'register'

    auth.py  

    auth.py
    # 用户认证
    from django.core.cache import cache
    from rest_framework.authentication import BaseAuthentication
    
    from UserAuth.models import UserModel
    
    
    class UserAuth(BaseAuthentication):
        # 验证user及token
        def authenticate(self, request):
            # 判断是否是get请求,其他请求直接可以访问
            if request.method == 'GET':
                # 从请求地址栏获取token(query_params)
                token = request.query_params.get('token')
                try:
                    u_id = cache.get(token)
                    user = UserModel.objects.get(pk=u_id)
                    return user, token
                except:  # 若验证没成功返回None
                    return

    permissions.py

    # permissions.py
    # 权限控制
    from rest_framework.permissions import BasePermission
    
    from UserAuth.models import UserModel
    
    
    class Userpermission(BasePermission):
        # 重写方法,进行权限限制
        def has_permission(self, request, view):
            # 针对get请求的权限控制
            if request.method == 'GET':
                # 在用户存在的情况下
                if isinstance(request.user, UserModel):
                    # 用户是超级用户返回True
                    return request.user.is_super
                return False
            return True
  • 相关阅读:
    Python基础
    SQL脚本
    PDF技术之-jasperreports的使用
    redis缓存和mysql数据库如何保证数据一致性
    理解MySQL的乐观锁,悲观锁与MVCC
    intellj idea创建maven项目一直处于加载的解决问题
    Linux目录详解,软件应该安装到哪个目录
    总结
    总结
    总结
  • 原文地址:https://www.cnblogs.com/Vera-y/p/12102330.html
Copyright © 2011-2022 走看看