2014-05-22 2 views
4

Pour citer le Django docs:Comment filtrer les paramètres sensibles du POST Django à partir des rapports d'erreur Sentry?

@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']) 

Dans l'exemple ci-dessus, les valeurs des paramètres et mot_de_passe POST credit_card_number seront cachés et remplacés par des étoiles (******) dans la demande de représentation dans les rapports d'erreurs, tandis que la valeur du paramètre name sera divulguée.

Pour masquer systématiquement tous les paramètres POST d'une demande dans les rapports d'erreur, ne fournissent aucun argument au décorateur de sensitive_post_parameters:

@sensitive_post_parameters() 
def my_view(request): 
    ... 

En tant que test, j'ai ajouté le code suivant à mon application 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) 

Quand je soumets ce formulaire par POST, je peux voir les valeurs des deux champs (y compris sensitive) clair comme le jour dans le rapport Sentry.

Qu'est-ce que je fais mal ici? J'utilise Django 1.6 et Raven 3.5.2.

Merci d'avance pour votre aide!

+0

Aussi lorsque 'DEBUG' est défini sur False? – toabi

+0

Oui, il doit être défini sur False. La ligne exacte dans mon fichier de paramètres est la suivante: DEBUG = (os.environ.get ('DJANGO_DEBUG_MODE', 'off') == 'on') Et actuellement, dans l'environnement Heroku, DJANGO_DEBUG_MODE = désactivé –

Répondre

4

Il s'avère que cela provient d'un bug dans Django lui-même!

Si vous n'avez pas modifié DEFAULT_EXCEPTION_REPORTER_FILTER dans votre fichier settings, vous obtenez le filtre par défaut de SafeExceptionReporterFilter.

Si vous avez utilisé le décorateur sensitive_post_parameters, cela se traduira par votre méthode d'appel de get_post_parametersSafeExceptionReporterFilter:

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 

Le problème avec ce qui précède est que bien qu'il va revenir correctement un QuerySet avec le sensible POST paramètres mis à CLEANSED_SUBSTITUTE ('********************') ... il ne sera en aucune manière modifier request.body.

Ceci est un problème lorsque vous travaillez avec Raven/Sentry pour Django, car il se trouve que la méthode get_data_from_request des DjangoClient premières tentatives de Raven pour obtenir POST paramètres de la demande de request.body:

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] 

Le plus rapide fix avéré impliquer uniquement le sous-classement DjangoClient et remplacer manuellement sa sortie avec l'nettoyée QuerySet produite par SafeExceptionReporterFilter:

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 
Questions connexes