码迷,mamicode.com
首页 > 数据库 > 详细

基于角色的权限控制系统(role-based access control)

时间:2018-10-13 02:22:43      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:简单   def   key   登录   return   closed   method   get   password   

  role-based access control(rbac),指对于不同角色的用户,拥有不同的权限 。用户对应一个角色,一个角色拥有若干权限,形成用户-角色-权限的关系,如下图所示。当一个用户进行访问数据时,根据其角色判断其拥有的权限,限定其操作。通过django实现一个简单的rbac app,简要记录下过程。

技术分享图片

1,数据库设计

  建立四张表,用户表,角色表,权限表和权限组表。models.py代码如下:

技术分享图片
from __future__ import unicode_literals
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=16)
    age = models.IntegerField()
    role = models.ForeignKey(to=Role)
    def __str__(self):
        return self.name

class Role(models.Model):
    title = models.CharField(max_length=32)
    permission = models.ManyToManyField(to=Permission)
    def __str__(self):
        return self.title

class Permission(models.Model):
    title = models.CharField(max_length=32)
    url = models.CharField(max_length=32)
    action = models.CharField(max_length=32)
    group = models.ForeignKey(to=PermissionGroup)
    def __str__(self):
        return self.title

class PermissionGroup(models.Model):
    title = models.CharField(max_length=32)
    def __str__(self):
        return self.title
models.py

  这里一条权限实际上对应一条url,表示对一张数据表的一个操作(增删改查),而权限分组则表明权限属于对那张表的操作。因此有几张可以操作的数据表应对应几个权限组,而每个权限组,应该都包括四个权限:增删改查。一条权限的数据信息如下图。这里只有用户表和角色表两张表可以操作,对应用户管理和角色管理两个权限组。

技术分享图片

2. 权限控制

  用户是通过url来访问数据,而一条url对应一个权限。因此当用户访问数据时,权限控制的流程是:
    a, 首先判断用户是否登录,未登录时重定向至登陆页面。

    b,用户登陆进来时,根据其角色判断拥有的所有权限,并将其权限表计入session中。

    c,用户登陆后,当其访问数据时,根据session中权限表判断,若无查看权限则直接拒绝,否则允许查看,进一步判断增删改权限来个性化前端显示页面。

  url代码如下:

# 总的一级路由 
from
django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r^admin/, admin.site.urls), url(r^login/, views.login), url(r‘‘,include(rbac.urls)) ] # rbac.urls代码,二级分发路由 urlpatterns = [ url(r^user/$, views.listUser), url(r^user/add/, views.addUser), url(r^user/edit/(\d+), views.editUser), url(r^user/delete/(\d+), views.deleteUser), url(r^role/$, views.listRole), url(r^role/add/, views.addRole), url(r^role/edit/(\d+), views.editRole), url(r^role/delete/(\d+), views.deleteRole), ]

  url权限的判断,通过自定义中间件来实现,将用户访问的url和其权限表url匹配,拥有权限时才允许通过,交给相应的视图函数处理。代码如下:

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect
import re
#自定义中间件
class ValidPermission(MiddlewareMixin):
    def process_request(self,request):
        current_path = request.path  # 拿到当前请求路径  ‘/user/‘
       
     #设置白名单,允许任何人访问的url valid_urls = [/login/,/admin/(.*)] for url in valid_urls: path = ^%s$%url ret = re.match(path, current_path) if ret: return None #对于没有登陆的用户重定向至登陆页面 user_id = request.session.get(user,[]) if not user_id: return redirect(/login/) #根据权限来匹配url,决定当前用户是否有访问权限 permission_list = request.session[permission_list] # print permission_list,current_path for permission in permission_list.values(): urls = permission[permission__url] for url in urls: path = ^%s$%url ret = re.match(path,current_path) if ret: request.actions = permission[permission__action] #[u‘list‘, u‘edit‘, u‘add‘] # print request.actions return None return HttpResponse(没有访问权限)

 

  登陆函数代码:

def login(request):
    if request.method==POST:
        name = request.POST.get(name)
        passsword = request.POST.get(password)
        # print name, passsword
        user_obj = models.User.objects.filter(name=name,password=passsword).first()
        if user_obj:
            request.session[user]=user_obj.pk
            initial_permission(request,user_obj)
            return redirect(/user/)
        else:
            return render(request,login.html)
    return render(request, login.html)

from rbac import models
def initial_permission(request,user):
    permissions = models.Role.objects.filter(user=user).values(permission__url,permission__action,permission__group_id).distinct()
    permission_list = {}
    for item in permissions:
        if item[permission__group_id] not in permission_list:
            permission_list[item[permission__group_id]]= {permission__url:[item[permission__url],],permission__action:[item[permission__action],]}
        else:
            permission_list[item[permission__group_id]][permission__url].append(item[permission__url])
            permission_list[item[permission__group_id]][permission__action].append(item[permission__action])
    #print permission_list
    request.session[permission_list] = permission_list
    # 按用户组权限id分组,得到如下的数据结构,即对两张表分别的操作权限
    # {1: {‘permission__url‘: [u‘/user/‘, u‘/user/edit/(\\d+)‘, u‘/user/add/‘],
    #      ‘permission__action‘: [u‘list‘, u‘edit‘, u‘add‘]},
    #  2: {‘permission__url‘: [u‘/role/‘], ‘permission__action‘: [u‘list‘]}}

    #设置菜单的显示权限数据
    menu_permissions = models.Role.objects.filter(user=user).values(permission__url,permission__action,permission__group__title).distinct()
    menu_permission_list=[]
    for item in menu_permissions:
        if item[permission__action] == list:         menu_permission_list.append((item[permission__url],item[permission__group__title]))
    request.session[menu_permission_list] = menu_permission_list
    # print menu_permission_list

  视图函数的处理主要时将数据和用户权限传给前端,前端根据权限来显示不同的页面(若用户拥有添加,删除,编辑权限,则显示增加,删除,编辑按钮,否则不显示),下面是查看用户表的视图函数和前端页面:

class PermissionAction(object):
    def __init__(self,actions):
        self.actions = actions
    def add_check(self):
        return add in self.actions
    def edit_check(self):
        return edit in self.actions
    def delete_check(self):
        return delete in self.actions
# 查看用户表的视图函数
def listUser(request):
    users = models.User.objects.all()
    user_id = request.session.get(user)
    user = models.User.objects.filter(id=user_id).first()
    permission_action = PermissionAction(request.actions)
    return render(request, rbac/listUser.html, locals())

listUser.html

{% extends rbac/base.html %}
{% block data_table %}
    <div>
        {% if permission_action.add_check %}
            <a href="/user/add/">
                <button class="btn btn-success" style="margin-bottom: 15px">添加用户</button>
            </a>
        {% endif %}
    </div>
    <table class="table table-bordered ">
        <thead>
            <tr>
                <th>用户名</th>
                <th>角色</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for user in users %}
                <tr>
                <td>{{ user.name }}</td>
                <td>{{ user.role }}</td>
                <td>
                    {% if permission_action.edit_check %}
                        <a href="/user/edit/{{ user.pk }}">
                            <button class="btn btn-success">编辑</button>
                        </a>
                    {% endif %}
                    {% if permission_action.delete_check %}
                        <a href="/user/delete/{{ user.pk }}">
                            <button class="btn btn-danger" style="margin-left:15px">删除</button>
                        </a>
                    {% endif %}
                </td>
                </tr>
            {% endfor %}
        </tbody>
        </table>
{% endblock %}

完整代码见github:https://github.com/silence-cho/Rbac

 

基于角色的权限控制系统(role-based access control)

标签:简单   def   key   登录   return   closed   method   get   password   

原文地址:https://www.cnblogs.com/silence-cho/p/9781237.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!