赞
踩
用户权限认证组件包括权限model类和中间件类
权限类
权限基本信息包括title:权限名称 url:权限具体url
角色类
角色类包括title:角色名称 permission:角色的权限
权限和角色多对多关系
用户类需要对Role类设置多对多映射
白名单类
白名单包括title:权限名称 url:权限具体url
白名单内存放的是系统放行不进行权限校验的url
登录验证包括title:url标题 url:具体url
登录验证表存放的是需要登录才能进行操作或权限校验的url,如果没有登录则会重定向到登录页面
models.py
- from django.db import models
-
-
- class Permission(models.Model):
- '''
- 权限基本信息包括title:权限名称 url:权限具体url
- '''
- title = models.CharField(max_length=32, verbose_name='权限名称')
- url = models.CharField(max_length=200, verbose_name='url')
-
- def __str__(self):
- return self.title
-
- class Meta:
- verbose_name = '权限'
- verbose_name_plural = verbose_name
-
-
- class Role(models.Model):
- '''
- 角色类包括title:角色名称 permission:角色的权限
- 权限和角色多对多关系
- 用户类需要对Role类设置多对多映射
- '''
- title = models.CharField(max_length=32, verbose_name='角色名称')
- permission = models.ManyToManyField(Permission, verbose_name='权限')
-
- def __str__(self):
- return self.title
-
- class Meta:
- verbose_name = '角色'
- verbose_name_plural = verbose_name
-
-
- class Whitelist(models.Model):
- '''
- 白名单包括title:权限名称 url:权限具体url
- 白名单内存放的是系统放行不进行权限校验的url
- '''
- title = models.CharField(max_length=32, verbose_name='权限名称')
- url = models.CharField(max_length=200, verbose_name='url')
-
- def __str__(self):
- return self.title
-
- class Meta:
- verbose_name = '白名单'
- verbose_name_plural = verbose_name
-
-
- class NeedLogin(models.Model):
- '''
- 登录验证包括title:url标题 url:具体url
- 登录验证表存放的是需要登录才能进行操作或权限校验的url,如果没有登录则会重定向到登录页面
- '''
- title = models.CharField(max_length=32, verbose_name='url标题')
- url = models.CharField(max_length=200, verbose_name='url')
-
- def __str__(self):
- return self.title
-
- class Meta:
- verbose_name = '登录验证表'
- verbose_name_plural = verbose_name
权限认证中间件实现了process_request和process_view方法。中间件在初始化时会从数据库更新白名单列表和需要登录认证的url列表,这个中间件实现了用户访问权限认证,登录认证功能。
verify.py
- from django.shortcuts import render, HttpResponse, redirect
- from permission.models import Whitelist, NeedLogin
- from django.utils.deprecation import MiddlewareMixin
- import re
- from django.conf import settings
-
-
- class VerifyPermissions(MiddlewareMixin):
- # 只在中间件加载时执行一次
- # 获取白名单列表
- whitelist = Whitelist.objects.values('url').all()
- # 获取需要登录的url列表
- needLogin_list = NeedLogin.objects.values('url').all()
-
- def process_request(self, request):
- '''
- 对用户的请求和登录验证的url进行匹配,如果匹配成功且用户没有登录,则重定向到登录页面
- 需要在settings.py配置LOGIN_URL
- :param request:
- :return:
- '''
- current_url = request.path
- # 从session中取用户登录的数据,在登录视图函数内,登录成功需要在session中存储登录用户信息,这里使用user作为登录用户信息的key
- user = request.session.get("user", "")
- # 校验是否是登录验证表的内容,如果是且已登录则放行,如果不是登录验证表的内容则会放行到urls.py,如果未登录则重定向到登录页面
- for url in self.needLogin_list:
- ret = re.fullmatch(url['url'], current_url)
- if ret:
- if user:
- return
- else:
- return redirect(settings.LOGIN_URL)
-
- def process_view(self, request, view_func, view_args, view_kwargs):
- '''
- 根据中间中process_*方法执行的顺序,process_view方法是在请求到达urls.py之后在执行view.py视图函数之前执行的
- 使用process_view方法不使用process_request是因为如果用户输入了找不到的路径,可以先提示404,不会先提示权限问题
- '''
- current_url = request.path
- # 校验是否是白名单的内容,如果是则放行
- for url in self.whitelist:
- ret = re.fullmatch(url['url'], current_url)
- if ret:
- return
- # 从session中获取权限列表
- permissions_list = request.session.get('permissions_list', [])
- # 校验是否是权限内的内容,如果不是提示权限不够
- for url in permissions_list:
- ret = re.fullmatch(url['url'], current_url)
- if ret:
- return
- else:
- # 可设置自定义页面
- return HttpResponse('权限不够')
admin.py
- from django.contrib import admin
- from permission.models import *
- from permission.verify import VerifyPermissions
-
-
- class WhitelistAdmin(admin.ModelAdmin):
- '''
- 由于只在中间件加载第一次时加载白名单,所以对白名单内容做修改时,应对中间件中内容更新
- '''
-
- def save_model(self, request, obj, form, change):
- obj.save()
- VerifyPermissions.whitelist = Whitelist.objects.values('url').all()
-
- def delete_model(self, request, obj):
- obj.delete()
- VerifyPermissions.whitelist = Whitelist.objects.values('url').all()
-
-
- class NeedLoginAdmin(admin.ModelAdmin):
- '''
- 由于只在中间件加载第一次时加载登录验证表,所以对登录验证表内容做修改时,应对中间件中内容更新
- '''
-
- def save_model(self, request, obj, form, change):
- obj.save()
- VerifyPermissions.needLogin_list = NeedLogin.objects.values('url').all()
-
- def delete_model(self, request, obj):
- obj.delete()
- VerifyPermissions.needLogin_list = NeedLogin.objects.values('url').all()
-
-
- admin.site.register(Permission)
- admin.site.register(Role)
- admin.site.register(Whitelist, WhitelistAdmin)
- admin.site.register(NeedLogin, NeedLoginAdmin)
组件Github地址:https://github.com/WPN0837/RBAC
PS:Github上是组件的一个使用示例
只需要把permission下的内容复制到需要权限认证的项目中即可使用
在使用这个组件的项目中注册这个组件,在settings.py的INSTALLED_APPS添加'permission.apps.PermissionConfig',例如:
INSTALLED_APPS = [ ''' 'permission.apps.PermissionConfig', ]
添加中间件,在settings.py的MIDDLEWARE添加'permission.verify.VerifyPermissions',例如:
MIDDLEWARE = [ ''' 'permission.verify.VerifyPermissions', ]
PS:VerifyPermissions一定要写在SessionMiddleware后面,因为VerifyPermissions使用到了session
在项目定义User类的地方需要先引入permission.models下的Role类
例如from permission.models import Role
再在User绑定User类与Role类多对多映射关系
具体如:
- class UserInfo(models.Model):
- username = models.CharField(max_length=20)
- pwd = models.CharField(max_length=20)
- # 绑定用户与角色多对多映射关系
- role = models.ManyToManyField(Role, verbose_name='角色')
-
- def __str__(self):
- return self.username
在配置文件settings.py文件中需要配置登录的URL,要与urls.py文件中相同,例如:
- # settings.py
- # 也可使用登录url的别名
- LOGIN_URL = "/login/"
- # urls.py
- urlpatterns = [
- path('admin/', admin.site.urls),
- path('', index),
- # 登录的url,也可以使用别名
- path('login/', login),
- ]
在用户登录视图函数里,如果登录成功应当把用户信息和用户权限信息保存到用户的session中,例如:
- def login(request):
- if request.method == 'GET':
- name = request.GET.get('name', '')
- pwd = request.GET.get('pwd', '')
- u = UserInfo.objects.filter(username=name, pwd=pwd).first()
- if u:
- # 保存用户信息
- request.session['user'] = name
- # 保存用户权限信息
- request.session['permissions_list'] = list(
- Permission.objects.filter(role__in=u.role.all()).values('url').all())
- return HttpResponse('登录成功')
- else:
- return HttpResponse('登录失败')
具体保存到session里的数据的key由中间件类VerifyPermissions的process_request(使用了user)和process_view(使用了permissions_list)方法里使用到session的地方决定,可自己修改。
在添加完组件后,首先迁移数据库文件,然后把中间件VerifyPermissions注释掉,再进入django admin管理后台,在白名单中添加/admin/.*这个url,权限名称可以设置成admin或者其他的,再取消中间件VerifyPermissions的注释,因为没有admin后台的url添加进白名单,会提示没有权限访问/admin/开头的url。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。