基于 Django框架实现,采用 RBAC 权限管理机制
-
用户表、角色表、权限表
-
用户表:账号、姓名、邮箱、添加时间、最后登录时间、账号是否禁止登录
-
角色表:商品管理员、订单管理员、超级管理员
-
资源列表:资源名称(项目模块名称),资源路径(后台路由)
-
资源分类:商品模块、订单模块、营销模块、权限模块、内容模块、其他模块
-
-
- RBAC角色权限管理机制实现思路
# 面向资源编程 https://www.shiyanlou.com/v1/books/ # 请求后端 books书籍表中数据 get post # 用户表 # 角色表 # 权限表 get/post/put/delete 对应关系
- 所有权限的本质是对数据库中表中数据增删改查的操作
- 而这些增删改查的操作是通过前端不同路由,通过get、post、put、delete方法操作数据库的
- 对权限的控制,最简单的方法就是判断当前用户是否可以对指定路由请求操作的权限
- 把角色和这个角色能够访问的 url 和 请求方式进行关联(因为正是的业务逻辑用户权限划分力度可能非常细致)
- 再简单的业务逻辑中这一张表就是权限表
| 路由 资源(可能对应的是后端路由的 name名称,可以通过name名称解析出对应路由) | 请求方式 | 说明 |
|---|---|---|
| https://www.shiyanlou.com/v1/books/ | get | 判断用户是否可以查询books表中数据 |
| https://www.shiyanlou.com/v1/books/ | post | 判断用户是否可以添加books表中数据 |
| https://www.shiyanlou.com/v1/books/ | put | 判断用户是否可以更新books表中数据 |
| https://www.shiyanlou.com/v1/books/ | delete | 判断用户是否可以删除books表中数据 |
-
后端如何判断用户权限
-
用户发送求方法 https://www.shiyanlou.com/v1/books/ 的url
-
后端首先查询时哪一个用户,然后查询当前用户的角色
-
最后判断这个角色是否可以访问 https://www.shiyanlou.com/v1/books/ 的对应方法即可
-
JWT接口安全登录验证
使用restful规范进行接口的开发和维护
- RESTful不是一种技术,而是一种接口规范,主要规范包括:1.请求方式、2.状态码、3、url规范、4、传参规范
- 请求方式method
GET :从服务器取出资源(一项或多项)
POST :在服务器新建一个资源
PUT :在服务器更新资源(客户端提供改变后的完整资源)
PATCH :在服务器更新资源(客户端提供改变的属性)
DELETE:从服务器删除资源
- 状态码
'''1. 2XX请求成功''' # 200 请求成功,一般用于GET与POST请求 # 201 Created - [POST/PUT/PATCH]:用户新建或修改数据成功。 # 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务) # 204 NO CONTENT - [DELETE]:用户删除数据成功。 '''2. 3XX重定向''' # 301 NO CONTENT - 永久重定向 # 302 NO CONTENT - 临时重定向 '''3. 4XX客户端错误''' # 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误。 # 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 # 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 # 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录。 # 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 # 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 # 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 '''4. 5XX服务端错误''' # 500 INTERNAL SERVER ERROR - [*]:服务器内部错误,无法完成请求 # 501 Not Implemented 服务器不支持请求的功能,无法完成请求 ```
- 面向资源编程: 路径,视网络上任何东西都是资源,均使用名词表示(可复数)
- 所有请求实际操作的都是数据库中的表,每一个表当做一个资源
- 资源是一个名称,所以RESTful规范中URL只能有名称或名词的复数形式
- https://api.example.com/v1/zoos
- https://api.example.com/v1/animals
- https://api.example.com/v1/employees
- 过滤,通过在url上传参的形式传递搜索条件
- https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
- https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
- https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
- https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
- https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
-
django的DRF
- 认证
- 权限
- 序列化
- 版本号
- 限流
使用websocket实现用户与旅行专家的在线聊天功能
- websocket
- webssh
- 什么是WebSSH?
- webssh 泛指一种技术可以在网页上实现一个 SSH 终端。
- ssh终端:用来通过ssh协议,连接服务器进行管理
- 运维开发方向:堡垒机登录、线上机器管理(因为运维人员不肯能24小时携带电脑)
- 在线编程:提供一个编程环境
- websocket(3w1h)
- 什么是websocket
- webSocket是一种在单个TCP连接上进行全双工通信的协议
- 客户端和服务器之间的数据交换变得更加简单,**允许服务端主动向客户端推送数据。
- 浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输
- websocket与http区别
- http请求建立连接只能发送一次请求,不能有服务器端主动向客户端发送请求
- websocket建立的长连接,一次连接,后续一直通信,这样节省资源,可以有客户端发送请求给服务器端
- 远古时期解决方案就是轮询
- 客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动(浪费流量和资源)
- webSocket应用场景?
- 聊天软件:最著名的就是微信,QQ,这一类社交聊天的app
- 弹幕:各种直播的弹幕窗口
- 在线教育:可以视频聊天、即时聊天以及其与别人合作一起在网上讨论问题…
- websocket原理
- websocket首先借助http协议(通过在http头部设置属性,请求和服务器进行协议升级,升级协议为websocket的应用层协议)
- 建立好和服务器之间的数据流,数据流之间底层还是依靠TCP协议;
- websocket会接着使用这条建立好的数据流和服务器之间保持通信;
- 由于复杂的网络环境,数据流可能会断开,在实际使用过程中,我们在onFailure或者onClosing回调方法中,实现重连
- websocket实现心跳检测的思路
- 通过setInterval定时任务每个3秒钟调用一次reconnect函数
- reconnect会通过socket.readyState来判断这个websocket连接是否正常
- 如果不正常就会触发定时连接,每4s钟重试一次,直到连接成功
- 如果是网络断开的情况下,在指定的时间内服务器端并没有返回心跳响应消息,因此服务器端断开了。
- 服务断开我们使用ws.close关闭连接,在一段时间后,可以通过 onclose事件监听到。
- 什么是websocket
# 后端的django代码 from django.shortcuts import render from dwebsocket.decorators import accept_websocket,require_websocket from django.http import HttpResponse def index(request): return render(request, 'index.html') from dwebsocket.backends.default.websocket import DefaultWebSocket # request.websocket就是DefaultWebSocket对象 tmp = [] # 只有加了这个装饰器,这个视图函数才能处理websocket请求 @accept_websocket def echo(request): if not request.is_websocket(): #判断是不是websocket连接 try: #如果是普通的http方法 message = request.GET['message'] return HttpResponse(message) except: return render(request,'index.html') else: '''1.实现消息推送''' tmp.append(request.websocket) # 把所有连接的websocket连接都加入列表中 # request.websocket = <dwebsocket.backends.default.websocket.DefaultWebSocket object at 0x00000272E69A4320> # failed:Invalid frame header:你的视图没有阻塞,请求过一次后服务器端就关闭连接了 # 所以使用for循环 request.websocket 对象就会调用 __iter__()方法,利用迭代器进行阻塞 for message in request.websocket: for ws in tmp: ws.send(message) '''2.实现聊天室思路''' # d = {} # 使用了一个dict来保存数据, # d['zhangsan'] = request.websocket # key值是用户身份,value值是dict类型的{username:websocket}。 # d['zhangsan'].send(message) # 发送消息到客户端 # d['lisi'].send(message) ==> request.websocket.send(message) # 这只是个思路,如果正式使用的话,肯定会对group封装,也不会只保存在内存中,需要保存到redis中去 # 并且对每个websocket对象设置有效期,过期清除,避免长期挂起状态消耗系统资源等 ```