1.权限控制表设计
内容
1. 什么是权限? 2. 为什么要有权限?不同用户拥有不同的功能 3. 在web开发中,什么是权限?url 代表 权限4. 开发一个权限的组件,为什么要开发组件?5. 表结构的设计# 第一版权限表 permissionid url 用户表id name pwd 用户和权限的关系表id user_id permission_id # 第二版权限表 permissionid url 角色表id name角色和权限的关系表id role_id permission_id 用户表id name pwd用户和角色的关系表id user_id role_id
首先打开空白项目:
web代表app
启动一下:
运行,看所有的地址:
从上图我们可以看出,是对两张表进行的增删改查操作.
客户管理:添加,编辑,删除
账户管理:添加缴费记录,
现在,我们需要做的就是将荃线进行分配
有权限能进行相关的操作,没有权限不能进行相关操作
这个app,在这里就是web就相当于是组件.
首先我们创建app
在Terminal中进行命令行操作.
结果:
这个时候,我们就创建好了rbac应用.
我们需要在settings.py中注册一下
注意,上边需要加上逗号
下面我们开始写表.
3个models,5张表
下面我们迁移到数据库中:
报错,上边这个表名,现在修改过来了
连接数据库sqllite
执行下面的两条命令
这个时候,我们将左边的数据库拖到右边就可以了
接下来,我们在查看一下在数据库中创建的表,这时候五张表都有了
下面我们需要在admin中创建权限对应关系:
首先,我们需要创建超级用户=>
上边是我们需要创建的超级用户的命令,以及账号和密码:
root&&root1234567
创建完成之后,我们需要注册models
运行程序,登录:
输入:(127.0.0.1:8000/admin/)进入下面的页面:
输入刚才创建的账户和密码:
这个时候,我们可以看到这些表,都已经注册进去了
现在我们开始录入,点击Permissions
点击添加权限:
开始一点一点拿
首先我们查看的是:
因为路径匹配是空的,不用管,我们只需要在路由分发下面的urls点击进入
拿到相应的url地址写入admin中
上边显示的是权限对象类型,都显示的是str,需要进行修改,
如下配置,展示的好看一些
我们需要看下,register
看一下源码:
列表需要展示的字段,通过配置下列admin里边的内容
下边是配置信息的来源
对比原来的信息:
下面是我们刷新后得到的信息:
这样所有的内容都显示出来了
再加上一条list_editable,使这里的title变成可编辑的
刷新:
我们直接点击编辑,进行save进行修改就可以改变信息了.
下面我们开始添加角色:
依然需要修改str方法,还有这个一开始的颜色是深的,也就是不填的,这里我们需要修改一下
这时候我们"刷新"一下页面,这样就可以正常显示了
CEO拥有所有的权限
角色创建好,并且分配好权限了
添加用户:
qiangge是秘书的角色,所以没有任何权限
alex是UFO的角色,所以只有查看的权限
我们将CEO修改成管理员,也就是拥有所有的权限
这个时候,root就拥有了所有的权限
这个时候我们分配权限就已经写好了
销售除了删除其他权限都有
权限分配给角色,角色再分配给用户的过程
我们可以通过用户拿角色,再通过角色拿到相应的权限.
这时候用户就拥有了权限
2.权限控制的流程
请求,响应的过程
wsgi:匹配web服务器和web应用程序的接口.,模块有哪些?django的有wsgiref用的是python自带的,性能比较低,真实环境中用的是uwsgi,帮助信息的收发.
中间件:
模板:(继承,组件,一些标签的用法)
{{ }}
{%%}
model通过做数据库映射的,进行ORM操作,注意这个不能帮助我们创建数据库
没有加上权限角色控制,正常走是:
浏览器请求=>wsgi=>中间件里边的process_request,然后执行=>urls.py匹配=>然后走视图函数=>中间件process_view方法
=>执行视图具体的逻辑=>
这个时候1.直接返回httpresponse,->中间件里边的process_response->wsgi(状态行,响应头和响应体)->浏览器
2.redirect相当于只是返回一个响应头,再走一次流程,再拿结果,这时候可能拿到的是render
这个时候,视图通过model拿数据库db中的数据,,再交给模板渲染,这个过程是在py文件中渲染的而不是html中渲染的,
也就是说在视图函数中渲染的.渲染完成生成一个httpresponse对象,在向后走流程..最后到达浏览器
思考:权限控制需要做哪些事情?
获取用户的权限信息,然后每次用户访问的时候,再对权限信息进行判断.有权限,拿到结果,没有权限,拿不到结果.
思考,代码应该怎么写在中间件中?中间件做权限的校验
中间件::权限校验,有权限,return返回None,没有权限,返回httpresponse,告诉没有权限.这样实现权限的控制.
权限信息的保存应该如何做?登录成功之后需要再保存权限信息.
思考,权限信息应该放在哪个位置?
在视图中:登录成功之后,保存用户的权限信息,保存在session中会好一些,理论上我们需要将session单独拿到一个地方放起来
默认是数据库中,也可以放在内存中,原因就是"快"
也就是登录之后,我们将权限信息放在session当中,下次登录的时候,需要中间件校验的时候.
直接将session存储的权限信息拿出来,再进行校验,
没有权限,就拒绝掉.这个就是整体的思路.
下面开始实现简单的代码.
3.登录后保存权限信息
我们将会login单独写在一个文件夹中
如果发送ajax需要用到type="button",但是现在我们不需要
此时运行:
输入用户和密码,点击登录,发送post请求,下面我们开始,获取请求和密码:
根据前端里边的input里边的name,,后端获取get的name
下面进行auth.py操作:
我们需要通过login.html渲染一下
点击,进入用户表
运行:下面得到的结果,输入用户和密码
服务端得到的结果:
如果想要具体的值应该,如何处理?
运行:
得到如下结果:
相当于程序走到下图的位置:
相当于查询上边的role表里边的角色id和name,也就是拿到角色的信息,现在我们想做的是拿到权限的信息.需要跨表
修改程序:
运行:这个时候得到角色的id&&name,权限的序号id
进一步修改:
现在我们想要权限的url和权限的title:
如何修改?
这样修改会报错,我们进行修改一下
这个时候得到的结果:
下面我们,循环打印:
运行:
登录之后,服务端得到的结果
看一下强哥,没有权限,应该怎样处理?
上边红框中直接写,相当于在roles后边加了all()的用法写的
也就是,如下图所示的写法:
现在我们加上过滤条件,将上边的all(修改成filter).也就是要权限permission__url不为空的内容
我们主要用的也就是permission__url键的值
修改完成,我们再运行,测试
点击"登录",这个时候就没有打印了,相当于是为空的去除掉
现在的情况是每个用户分配一个权限.
我们将所有的角色都加上,
点击保存:
然后,我们登录"root"&&"123"账户
后端得到结果:
先拿角色,再拿权限,但是现在存在重复的问题,应该如何处理?通过去重来进行处理
现在我们需要将筛选条件,去掉id和name,保留后边的两个字段就可以了
然后再用distinct,进行去重
运行:
后端得到8个权限
运行:
报错:
问题在于,存储的这一步,没有进行序列化
我们将权限信息,放到session中,需要进行json序列化permission_query不是json序列化对象,只需要转化成可以序列化的对象就可以了
我们需要将字典放入列表当中,
我们只要刷新一下,就可以得到数据:
现在需要重定向到首页
我们需要再写一个首页:
现在我们需要做反向解析,
在登录页面中重定向到首页
重启,alex&&123登录,现在我们还没有进行权限的验证,但是这里我们已经可以登录,见下图看一下,
现在我们我们在上面已经处理完了,"登录成功后,保存用户的权限信息"
3.权限校验的中间件
现在需要做的是,在中间件进行权限的认证功能.
我们下面开始写中间件,首先创建,
首先找到的是settings.py里边的安全中间件
点击进入:"安全中间件"
找到上边的包.我们对上边的包进行替换.
设置的类,考虑应该分几步做这个事情?
下面我们需要看一下,当前权限的列表
然后我们要将中间件注册到settings.py文件中.(先路径,后类名)
重启一下,我们刷新一下页面:
现在登录的是alex账户,下面得到的是1个列表内有两个字典
下面的判断方法是,访问的页面是否在session中存在.通过这个条件进行判断,因为我们在auth.py里边已经转化成了列表了
再看一下auth.py里边的内容:
这个时候,我们再访问下面的地址,显示"没有访问的权限"
分析过程:先走中间件,执行process_request方法,然后获取到当前的地址url,
后端的permission_list列表打印:拿到下面的地址
访问的地址和下面我们,拿到的地址不匹配,我们就得到了"没有访问的权限",这个页面
这个就说明,没有这个权限了,下面的这个login地址也是没有权限的.
这个地方需要设置一个白名单
登录,注册,以及url以admin开头的字段:也就是设置一个if条件条件判断进行return通过.
注意,这个login和index的路径需要在后边加上/
这样就可以登录了.reg也会报注册的错
admin也可以走:
但是下面这种写法,可以实现功能,但是不合适,需要修改的话怎么处理?
也就是说,在我们的settings.py文件中,进行配置,将上边的代码注释掉
在settings.py里边添加上白名单:
这个时候,我们需要在rbac.py里边引入settings.py文件
我们开始,循环拿列表里边的内容:
在配置中的login和reg是没有问题的,但是admin是存在问题的
上边的for+if的方式不太严谨,我们可以用正则进行匹配
下面复习一下正则:
import re
re.search() #从整个字符串里边拿取一个
re.match() #从头匹配,找到则返回
re.findall() #找到所有符合的结果
上边括号内的内容,前面是正则,后边是要匹配的内容
综合上述,match比较合适
下图是我们匹配到的一个结果:
如果匹配不到,怎么办?返回的结果是None
因此这里我们用正则就可以进行操作
下面,我们需要严谨一点,进行处理:严格匹配
这个时候表示,所有的,也就是说,这个settings.py白名单里边的是正则bds
这样就完成了匹配:
运行:admin没有问题
login也是没有问题的
reg也是没有问题的,上边报错的原因是没有这个页面,所以我们没有找到
这样我们就实现了白名单
点击"登录",我们会发现没有权限
客户/列表这个权限,我们是有的
上图是"添加权限"也是有的
上图显示没有编辑权限和删除权限
之所以显示"没有权限",是因为我们再来浏览器得到的地址和session内的地址不同,浏览器触发的事件中,多了数字.
我们对权限进行修改:注意:这个地方不能加上^和$
最后得到的结果:
这个时候,我们得到了下面的url.正则匹配的方式
下面是登录页面:
点击"登录"
下面的页面:
添加:
编辑:
删除也是没有问题的
下面我们解决index的页面
思考:有些地址不是权限:像index是首页,只需要登录,就可以查看
我们可以思考,登录成功之后添加一个状态,有了登录之后的状态,我们就可以访问index页面了
在中间件中添加一个,是否登录的状态
下面我们再在rbac.py里边操作,获取完白名单之后,先处理登录与否的状态,然后再处理"获取当前用户的权限"
需要先导入,后边的两个模块
这类地址,像index可能有这么一类地址,除了上边的操作,我们也可以写在settings.py里边.
和白名单是非常类似的:也就是首页地址,下面我们进行处理一下.
下面,我们运行程序,登录下,看看是否可以登录:
点击"登录",这个时候,我们可以成功跳转到"首页"
这个时候,我们就处理好权限的控制了
4.总结:
权限控制:
如何实现权限控制的?
也就是,如何记录权限的?
总结:
总结:1. 权限控制1. 表结构的设计3个model 5张表权限表 url title 角色表 name 多对多 permissions 或者permission用户表 name pwd 多对多 roles角色和权限的关系表 用户和角色的关系表 2. 流程:1. 登录get:通过中间件的白名单 re 获取到登录页面post: 通过中间件的白名单认证成功 保存权限信息- ORM 去空的权限 去重 - request.session json序列化2. 免认证的访问判断登录状态获取免认证的地址 匹配 re3. 需要的校验的地址- 中间件从session中获取到当前用户的权限信息循序权限信息 和 当前的url 匹配匹配成功 return 正常流程所有都匹配不成功 没有权限 return HttpResponse('没有访问的权限')
rbac.py在这个程序中代表中间件
这个时候,存在这个问题
这个时候,就跳转到响应的页面:
点击"登录"