TOP

django 实现审计中心中间件

需求描述

起一个中间件将所有的请求拦截进行校验的同时记录相关的访问信息

主要用于审计职能, 需记录用户信息, 访问资源, 访问方式以及请求结果等

需求实现

主要结合中间件的  process_request  和  process_response  来实现

请求的信息记录主要由以下内置便利来截取

request.path    请求url
request.user    请求用户
request.META['REMOTE_ADDR']    请求终端IP

request.GET    GET请求参数
request.body    POST请求参数

response.status_code    响应状态码
response.reason_phrase    响应结果

 

问题处理

其中会遇到一些问题如 

'WSGIRequest' object has no attribute 'data'

 

在视图中可以通过 request.data 直接调取 POST 请求的参数信息. 但是在中间件中是不可行的

 

还有这个问题

You cannot access body after reading from request‘s data stream

 

问题较为复杂,大体意思是不允许直接使用

但是解决方式也较为简单, 通过复制一个新的变量即可

re_request_body = getattr(request,'_body',request.body)
print(re_request_body)

 

注意: 此方法只适用于在  process_request  中

解决方式如下, 中间件内同一个作用域下的数据是互通的, 写入传递记录即可

详细代码实现

class AuditMiddleware(MiddlewareMixin):
    re_request_body = None
    def process_request(self, request):
        self.re_request_body = None
        if request.method != "GET":
            body_content = getattr(request, '_body', request.body)
            self.re_request_body = eval(body_content.decode("utf-8"))
            print(self.re_request_body)
    def audit_record(self, request, response):
        re_request_body = self.re_request_body
        Audit.objects.create(
            path=request.path,
            request_method=request.method,
            user=request.user,
            parameter=request.GET if request.method == "GET" else re_request_body,
            ip_addr=request.META['REMOTE_ADDR'],
            status_code=response.status_code,
            reason_phrase=response.reason_phrase,
        )
        self.re_request_body = None
        return

 

暂不清楚中间件的每次请求都会实例化还是会单例, 如果单例的话考虑会出现后面是post 请求覆盖不到前面的情况

所以保险起见每次用完就清空中间变量最好

 

posted @ 2022-07-08 11:59  羊驼之歌  阅读(212)  评论(0编辑  收藏  举报