基于RBAC权限验证, 中间价middleware实现, views 登录视图代码
废话不多说 上代码:
基础实现:
rom django.shortcuts import HttpResponse, redirect, render
from django.http import FileResponse, JsonResponse from rbac.models import * def login(request):
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd") current_user = UserInfo.objects.filter(name=user, password=pwd).first()
'''SELECT "rbac_userinfo"."id", "rbac_userinfo"."name", "rbac_userinfo"."password", "rbac_userinfo"."email"
FROM "rbac_userinfo"
WHERE ("rbac_userinfo"."name" = 'alex' AND "rbac_userinfo"."password" = '123')
ORDER BY "rbac_userinfo"."id" ASC LIMIT 1; '''
if not current_user:
return render(request, "login.html", {"msg": "username or password is wrong"}) # 根据当前用户信息,获取当前用户所拥有的所有的权限(queryset对象 是不能直接放入,session中的)
permission_queryset = current_user.roles.filter(permissions__isnull=False).values("permissions__url").distinct()
'''
SELECT DISTINCT "rbac_permission"."url" FROM "rbac_role"
INNER JOIN "rbac_userinfo_roles"
ON ("rbac_role"."id" = "rbac_userinfo_roles"."role_id")
INNER JOIN "rbac_role_permissions"
ON ("rbac_role"."id" = "rbac_role_permissions"."role_id")
INNER JOIN "rbac_permission"
ON ("rbac_role_permissions"."permission_id" = "rbac_permission"."id")
WHERE ("rbac_userinfo_roles"."userinfo_id" = 1 AND "rbac_role_permissions"."permission_id" IS NOT NULL);
''' # 根据得到的queryset 循环遍历, 得到其中的 每一个权限的 url. 然后将每一个url 放入一个列表中。进而保存到session
permission_list = [item.get("permissions__url") for item in permission_queryset]
print(permission_list)
request.session["permissions__url"] = permission_list
return redirect("/customer_list/")
return render(request, "login.html", locals())
login
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
import re class CheckPermission(MiddlewareMixin):
'''用户权限信息的校验'''
def process_request(self, request):
'''当用户请求进入时 触发执行'''
'''
1. 获取当前用户请求的url
2. 获取当前用户在session中保存的 权限列表 [......]
3. 当前请求url 在 session中, 就可以,进行访问
'''
'''有时我们需要 一些url无需权限, 就可以登录。 比如login登录页面, amdin后台管理(这个不需要我们的中间件去控制权限,所以这里直接放过)'''
'''我们尽量使用re 的正则匹配来做这件 事情。因为 我们不可能把 所有的url 都写一遍放到 白名单中。'''
'''我这里使用的是 re.match() 他的作用是, 从一个字符串的起始位置 开始匹配一个模式。 如果第一个字符就不匹配 就直接返回None'''
''' re.match('/admin/',"/admin/")可以匹配成功, re.match('/admin/',"/admin/asdkd/asd")也是可以匹配成功的。
所以已admin起始的url都属于白名单''' valid_url_list = ["/login/", "/admin/"] # 一个白名单
current_url = request.path_info # 得到当前访问的url
for valid_url in valid_url_list:
if re.match(valid_url, current_url): # 白名单中的url 无需权限验证
return None
# 我这里的return None 意思是: 如果在白名单中 我这里就直接return 函数中后续的代码就不会去执行,也就是不会再去
# 进行验证的操作。 但是因为return 的是 None, 并不会影响整体的流程, 依然会继续执行后面的中间件,视图函数。
# 如果 不是return None 的话。就不会走到视图函数中。 permission_list = request.session.get("permissions__url") # 得到保存在session中的 权限信息。 if not permission_list:
'''用户未登录前 session为空, 所以直接返回就好了'''
return HttpResponse("您没有访问权限...请联系管理员") # permission_list 中的url 是包含正则的。 所以要使用re模块来进行验证
flag = False
# 需要注意的是,列表循环。进行匹配 只要有一个能匹配成功就可以访问, 所以未匹配成功 也不能够影响后面的匹配
# 所以 就不能使用else。
# 所以 添加一个flag变量 默认为False 只要有一个成功,flag就为Ture, 最终通过判断flag 确定是否拥有访问权限
for url in permission_list:
reg = "^%s$" % url # 正则匹配match 都是从其实开始匹配,但是没有限定结束。
# 所以要给当前的url 添加 ^ $ 开始和终止符。
if re.match(reg, current_url):
flag = True
break # 只要有一个匹配成功,就直接退出,剩下的就不需要进行匹配了
if not flag:
return HttpResponse("无权访问")
middleware
代码完善:
上面的代码, 功能上是OK的, 但是不够profession。
我们希望的是 一个,比较通用的组件。 而权限初始化这部分的代码,我们可以单独的提取出来,放入我们的rbac组件中。
与我们的登录 进行一个 解耦。 这样 权限初始化这部分,独立出去之后,就不需要再重复的 编写:
1.用户登录与权限初始化的 拆分:
from django.shortcuts import HttpResponse, redirect, render
from rbac.models import *
from rbac.service.init_permission import init_permission def login(request):
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd") current_user = UserInfo.objects.filter(name=user, password=pwd).first() if not current_user:
return render(request, "login.html", {"msg": "username or password is wrong"}) init_permission(current_user, request)
return redirect("/customer/list/")
return render(request, "login.html", locals())
web.views.account
def init_permission(current_user, request):
'''
:param current_user: 当前请求 用户对象
:param request: 当前请求 数据
:return:
'''
# 2. 权限 初始化
permission_queryset = current_user.roles.filter(permissions__isnull=False).values("permissions__url").distinct()
permission_list = [item.get("permissions__url") for item in permission_queryset]
request.session["permissions__url"] = permission_list
rbac.service.init_permission
这样我们将,这部分的功能, 独立到我们的RBAC 权限组件中。 需要使用的时候, 直接调用即可。
2. 我们已经完成了对 功能的拆分。 人的嫌麻烦程度是无限的。
如果有一天,我想对 request.session["permissions__url"] = permission_list session的key 进行修改的时候,我就不得不去找到所有的 代码然后再去修改一遍。 这是非常不友好的,so We need a solution:
思路:我们可以在 项目的settings中,添加一个 对这个 key 的 配置项:
比如: PERMISSIONS_SESSION_KEY = "permissions__url"
from django.conf import settings def init_permission(current_user, request):
'''
:param current_user: 当前请求 用户对象
:param request: 当前请求 数据
:return:
'''
# 2. 权限 初始化 permission_queryset = current_user.roles.filter(permissions__isnull=False).values("permissions__url").distinct()
permission_list = [item.get("permissions__url") for item in permission_queryset]
request.session[settings.PERMISSIONS_SESSION_KEY] = permission_list
rbac.service.init_permission
这样子, 我们以后保存的时候session的 时候, 就只需要引入settings中的 PERMISSIONS_SESSION_KEY 就ok了
当然,在中间件需要取出 session的时候,也是同样的操作:
class CheckPermission(MiddlewareMixin):
'''用户权限信息的校验'''
def process_request(self, request):
'''当用户请求进入时 触发执行'''
'''
1. 获取当前用户请求的url
2. 获取当前用户在session中保存的 权限列表 [......]
3. 当前请求url 在 session中, 就可以,进行访问
''' valid_url_list = ["/login/", "/admin/"]
current_url = request.path_info
for valid_url in valid_url_list:
if re.match(valid_url, current_url):
return None
permission_list = request.session.get(settings.PERMISSIONS_SESSION_KEY) if not permission_list:
return HttpResponse("您没有访问权限...请联系管理员") flag = False
for url in permission_list:
reg = "^%s$" % url
if re.match(reg, current_url):
flag = True
break
if not flag:
return HttpResponse("无权访问")
基于RBAC权限验证, 中间价middleware实现, views 登录视图代码的更多相关文章
- Thinkphp3.2.3中的RBAC权限验证
最近在用TP的RBAC权限控制,在这里记录学习一下.先来看看相关的概念 一.相关概念 访问控制与RBAC模型1.访问控制: 通常的多用户系统都会涉及到访问控制,所谓访问控制,是指通过某种 ...
- 一文读懂k8s rbac 权限验证
自我认为的k8s三大难点:权限验证,覆盖网络,各种证书. 今天就说一下我所理解的权限验证rbac. 咱不说rbac0,rbac1,rbac2,rbac3.咱就说怎么控制权限就行. 一.前言 1,反正R ...
- 物联网架构成长之路(31)-EMQ基于HTTP权限验证
看过之前的文章就知道,我之前是通过搞插件,或者通过里面的MongoDB来进行EMQ的鉴权登录和权限验证.但是前段时间发现,还是通过HTTP WebHook 方式来调用鉴权接口比较适合实际使用.还是实现 ...
- 基于RBAC权限管理的后台管理系统
在摸爬滚打中渐渐理解了RBAC权限管理是个什么玩意. RBAC的基本概念: **RBAC认为权限授权实际上是Who.What.How的问题.在RBAC模型中,who.what.how构成了访问权限三元 ...
- 下面介绍一个 yii2.0 的 Rbac 权限设置,闲话少说,直接上代码,
1.首先我们要在组件里面配置一下 Rbac ,如下所示(common/config/main-local.php或者main.php). 'authManager' => [ 'class' ...
- Asp.net Mvc 身份验证、异常处理、权限验证(拦截器)实现代码
本问主要介绍asp.net的身份验证机制及asp.net MVC拦截器在项目中的运用.现在让我们来模拟一个简单的流程:用户登录>权限验证>异常处理 1.用户登录 验证用户是否登录成功步骤直 ...
- TP支持菜单动态生成RBAC权限系统数据库结构设计方案
最简单基于RBAC权限系统数据库结构设计 包括如下几个表 1. 用户表 -- Table "t_user" DDL CREATE TABLE `t_user` ( `id` int ...
- 如何在数据库中进行RBAC权限应用
上周我们发了一篇关于"删库跑路"引发了大家对于数据安全的思考,而权限管理又跟数据安全密不可分.权限管理作为数据系统的重要组成部分,通过控制账号的可支配能力,防止因用户操作不当导致的 ...
- .net web api 权限验证
做一个登录权限验证. 开始吧. using System; using System.Collections.Generic; using System.Drawing; using System.D ...
随机推荐
- 初级JS
唐太宗 李世民 杀了大哥 和弟弟 登上的皇位 一个人当皇帝 排他性是指一种物品具有可以阻止其他人使用该物品的特性. 排他性思想: 在程序中但凡是遇到只让自己怎么样,不让别人怎么样的效果,都 ...
- Jupter 7个进阶功能
1. 执行shell命令 Shell是一种与计算机进行文本交互的方式. 一般来讲,当你正在使用Python编译器,需要用到命令行工具的时候,要在shell和IDLE之间进行切换. 但是,如果你用的是 ...
- 最小生成树二·Kruscal算法
描述 随着小Hi拥有城市数目的增加,在之间所使用的Prim算法已经无法继续使用了——但是幸运的是,经过计算机的分析,小Hi已经筛选出了一些比较适合建造道路的路线,这个数量并没有特别的大. 所以问题变成 ...
- 微信小程序--页面传参
场景: A页面字段---传递到-->B页面 A页面wxml: wx:for----习惯用<block> 设置所点击的值----data-xxx 获取所点击的值---e.current ...
- kafka 删除topic清空数据
原 kafka 删除topic清空数据 2018年11月20日 18:17:50 Ming! 阅读数:1391 版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载. https://bl ...
- 04_web基础(七)之jsp
39.jsp与el表达式引入 JSP:Java Server Pages:Java的服务网页(Java动态网页):=========================================== ...
- 大型运输行业实战_day11_2_事务理论与实际生产配置事务管理
1.什么是事务(Transaction:tx) 数据库的某些需要分步完成,看做是一个整体(独立的工作单元),不能分割,要么整体成功,要么整体生效.“一荣俱荣,一损俱损”,最能体现事务的思想.案例:银行 ...
- cdnbest如何检查https证书是否有效
注意: 用此方法检查ssl证书是否有效,此帐号下必须有有效的cdn节点,因为这个证书是要通过底层的cdn节点来检测的 1. 在站点设置中如下图点打开添加ssl证书 2.加完证书后点检查,打勾就表示证书 ...
- wamp 安装redis扩展
phpredis扩展下载地址 http://windows.php.net/downloads/pecl/snaps/redis/ 1.选择redis DLL文件扩展 phpinfo 查看VC版本 ...
- SpringBoot @Value读取properties文件的属性
SpringBoot在application.properties文件中,可以自定义属性. 在properties文件中如下示: #自定义属性 mail.fromMail.addr=lgr@163.c ...