引用Django文档:
@sensitive_post_parameters('pass_word', 'credit_card_number')
def record_user_profile(request):
UserProfile.create(user=request.user,
password=request.POST['pass_word'],
credit_card=request.POST['credit_card_number'],
name=request.POST['name'])
在上面的示例中,在错误报告中的请求表示中,pass_word和credit_card_number POST参数的值将被隐藏并替换为星号(******),而name参数的值将被公开。
要在错误报告中系统地隐藏请求的所有POST参数,请不要向sensitive_post_parameters装饰器提供任何参数:
@sensitive_post_parameters()
def my_view(request):
...
作为测试,我在Django 1.6应用程序中添加了以下代码:views.py:
@sensitive_post_parameters('sensitive')
def sensitive(request):
if request.method == 'POST':
raise IntegrityError(unicode(timezone.now()))
return render(request, 'sensitive-test.html',
{'form': forms.SensitiveParamForm()})
forms.py:
class SensitiveParamForm(forms.Form):
not_sensitive = forms.CharField(max_length=255)
sensitive = forms.CharField(max_length=255)
当我通过POST
提交此表单时,我可以在Sentry报告中看到两个字段(包括sensitive
)的值。
我在这里做错了什么?我使用的是Django 1.6和Raven 3.5.2。
提前感谢您的帮助!
原来这是由Django本身的一个bug引起的!
如果你没有改变settings
文件中的DEFAULT_EXCEPTION_REPORTER_FILTER
,你会得到SafeExceptionReporterFilter
的默认过滤器。
如果您使用了sensitive_post_parameters
装饰器,这将导致您调用SafeExceptionReporterFilter
的get_post_parameters
方法:
def get_post_parameters(self, request):
"""
Replaces the values of POST parameters marked as sensitive with
stars (*********).
"""
if request is None:
return {}
else:
sensitive_post_parameters = getattr(request, 'sensitive_post_parameters', [])
if self.is_active(request) and sensitive_post_parameters:
cleansed = request.POST.copy()
if sensitive_post_parameters == '__ALL__':
# Cleanse all parameters.
for k, v in cleansed.items():
cleansed[k] = CLEANSED_SUBSTITUTE
return cleansed
else:
# Cleanse only the specified parameters.
for param in sensitive_post_parameters:
if param in cleansed:
cleansed[param] = CLEANSED_SUBSTITUTE
return cleansed
else:
return request.POST
上面的问题是,虽然它将正确返回QuerySet
,敏感的POST
参数设置为CLEANSED_SUBSTITUTE
('********************'
)…不会改变request.body
.
这是一个在Django中使用Raven/Sentry的问题,因为Raven的DjangoClient
的get_data_from_request
方法首先尝试从request.body
获取请求的POST
参数:
def get_data_from_request(self, request):
[snip]
if request.method != 'GET':
try:
data = request.body
except Exception:
try:
data = request.raw_post_data
except Exception:
# assume we had a partial read.
try:
data = request.POST or '<unavailable>'
except Exception:
data = '<unavailable>'
else:
data = None
[snip]
最快的修复方法是将DjangoClient
子类化,然后用SafeExceptionReporterFilter
生成的经过清理的QuerySet
手动替换它的输出:
from django.views.debug import SafeExceptionReporterFilter
from raven.contrib.django.client import DjangoClient
class SafeDjangoClient(DjangoClient):
def get_data_from_request(self, request):
request.POST = SafeExceptionReporterFilter().get_post_parameters(request)
result = super(SafeDjangoClient, self).get_data_from_request(request)
result['sentry.interfaces.Http']['data'] = request.POST
return result