基于django内置的权限管理系统写一套自己的权限管理


#基础知识 #rest framwork 的内置admin的权限控制中,默认为每个model生成了3个权限: add update delete #将信息保存在内置的content_type表中,表中保存了model所在的app 和model的三个权限 #admin的权限管理系统由内置的三张表组成 user group permission 三张表之间的关系又由另外3张表来连接 #他们的关系如下图  #利用内置权限管理定制自己所需要的权限系统的方法 #只需做一些稍微的修改,便可以使用内置的权限系统,为自己所用了 #1 写自己的user表,继承AbstractUser,可以添加额外的字段,但默认已经有了用户名和密码 class Manager(AbstractUser): mobile_number = models.CharField(max_length=20, verbose_name='手机号') #定制需要的登陆验证方法,默认的登陆验证是用户名和密码 class CustomBackend(ModelBackend): """     定义用户登录方式(手机号/邮箱登录) """  def authenticate(self, request, username=None, password=None, **kwargs): try: manager = Manager.objects.get(Q(mobile_number=username) | Q(email=username)) if manager.check_password(password): return manager else: raise ValidationError('用户名或密码错误', code=status.HTTP_400_BAD_REQUEST) except Exception as e: raise ValidationError('用户名或密码错误', code=status.HTTP_400_BAD_REQUEST) #由于默认只有增改删3个权限,我们要为它添加一个查看的权限,为此我们要添加自定义权限 #在model中添加如下信息 class Kids(models.Model): class Meta: permissions = ( ('view_kids_list', '查看儿童信息表'), ) #为用户分配权限 #检验用户是否有的权限 class KidsViewSet() permission_classes = (permissions.DjangoModelPermissions,) #添加权限限制 def list(self, request, *args, **kwargs): user = request.user if user.has_perm('kids.view_kids_list'): #‘app名.权限名’ return super(KidsViewSet, self).list(request, *args, **kwargs) else: data = {'detail': '没有权限'} return Response(data, status=status.HTTP_403_FORBIDDEN) #模仿admin修改密码 #加密以及解密方法 class ManagerPasswordSerializer(serializers.Serializer): #添加额外字段的方法 old_password = serializers.CharField(source='my_field') password = serializers.CharField(required=True) class Meta: model = Manager fields = '__all__'

        
class ManagerPasswordViewSet(mixins.UpdateModelMixin, viewsets.GenericViewSet): """  用户修改密码接口 """     queryset = Manager.objects.all() versioning_class = URLPathVersioning serializer_class = serializers.ManagerPasswordSerializer def update(self, request, version, *args, **kwargs): data = request.data new_password = data['password'] old_password = data['old_password'] from django.contrib.auth.hashers import check_password, make_password #验证旧密码是否正确 username = request.user.username password = Manager.objects.filter(username=username).values('password') if check_password(old_password, password[0]['password']): #修改为新密码 Manager.objects.filter(username=username).update(password=make_password(new_password)) return Response('修改成功', status=status.HTTP_200_OK) else: return Response('密码输入错误', status=status.HTTP_400_BAD_REQUEST) #最后,只要给用户分配了相应的权限,就可以轻松的拥有一套权限系统啦 #可以在用户登陆时给用户发送一个权限菜单 #思路是: #1 新建一个菜单表,存储一级二级菜单的信息,每个对应content_type表中的每个model #2 用户登陆时获取用户的权限信息(具体形式是对哪些model的什么权限),在全部的权限(菜单表)中筛选出用户对哪些model具有权限,再拼接出url, #3 按菜单表中的信息形成嵌套层级关系,最后返回给用户菜单信息 class Menu(models.Model): """  用户权限菜单表 """     content_model = models.ForeignKey(ContentType, null=True) first_menu_name = models.CharField(max_length=100, null=True) second_menu_name = models.CharField(max_length=100, null=True) second_menu_parent = models.ForeignKey('Menu', null=True) second_menu_url = models.URLField(null=True) create_date = models.DateTimeField(verbose_name='申请日期', default=datetime.now, null=True) def __str__(self): return self.id class Meta: verbose_name = "菜单" verbose_name_plural = verbose_name def list(self, request, *args, **kwargs): # 获取域名和版本 url = request.get_host() version = request.version # 用户所有的model权限 permission_list = request.user.get_all_permissions() username = request.user.username user_model = set() for i in permission_list: model = i.split('_')[-1] user_model.add(model) user_model1 = list(user_model) first_info = Menu.objects.filter(content_model__model__in=user_model1, first_menu_name__isnull=False, second_menu_url__isnull=False).values('id', 'first_menu_name', 'second_menu_url') second_info = Menu.objects.filter(content_model__model__in=user_model1, second_menu_name__isnull=False, ).values('second_menu_name', 'second_menu_url', 'second_menu_parent_id') # 拼接完整url,替换原来的url for i in first_info: if not i['second_menu_url']: continue i['second_menu_url'] = url + '/' + version + i['second_menu_url'] for i in second_info: if not i['second_menu_url']: continue i['second_menu_url'] = url + '/' + version + i['second_menu_url'] # 形成嵌套关系 for i in first_info: i['child'] = [] for j in second_info: if i['id'] == j['second_menu_parent_id']: i['child'].append(j) first_info = list(first_info) first_info.append({'username': username}) return Response(first_info) #缺陷: 权限只能限制到表的级别,不能限制到操作action的级别

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM