Ticket #510: csrf-protection.patch
File csrf-protection.patch, 7.1 KB (added by , 19 years ago) |
---|
-
models/auth.py
222 222 def _module_log_action(user_id, content_type_id, object_id, object_repr, action_flag, change_message=''): 223 223 e = LogEntry(None, None, user_id, content_type_id, object_id, object_repr[:200], action_flag, change_message) 224 224 e.save() 225 226 class CsrfToken(meta.Model): 227 token = meta.CharField(maxlength=200) 228 issued = meta.DateTimeField(auto_now=True) 229 user = meta.ForeignKey(User) 230 class META: 231 module_name = 'csrf' 232 verbose_name_plural = 'CSRF tokens' 233 db_table = 'auth_csrf_tokens' 234 ordering = ('-issued',) 235 236 def __repr__(self): 237 return self.token 238 -
conf/admin_templates/delete_confirmation_generic.html
2 2 3 3 {% block content %} 4 4 5 {% if csrf_failed %}<p class="errornote">CSRF protection: Please re-submit.</p>{% endif %} 6 5 7 {% if perms_lacking %} 6 8 <p>Deleting the {{ object_name }} "{{ object }}" would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:</p> 7 9 <ul> … … 15 17 <form action="" method="post"> 16 18 <input type="hidden" name="post" value="yes" /> 17 19 <input type="submit" value="Yes, I'm sure" /> 20 {% load csrf %}{% csrf_token %} 18 21 </form> 19 22 {% endif %} 20 23 -
templatetags/csrf.py
1 from django.core import template 2 from django.models.auth import csrf 3 import random, md5, datetime 4 5 class CsrfTokenNode(template.Node): 6 def render(self, context): 7 token = md5.new(str(random.random())).hexdigest() 8 ct = csrf.CsrfToken(None, token, 9 datetime.datetime.now(), context['user'].id) 10 ct.save() 11 return '<input type="hidden" name="csrf_token" value="%s">' % token 12 13 def csrf_token(parser, token): 14 """ 15 {% csrf_token %} 16 """ 17 return CsrfTokenNode() 18 19 template.register_tag('csrf_token', csrf_token) -
views/admin/main.py
588 588 if opts.admin.save_on_top: 589 589 t.extend(_get_submit_row_template(opts, app_label, add, change, show_delete, ordered_objects)) 590 590 t.append('{% if form.error_dict %}<p class="errornote">Please correct the error{{ form.error_dict.items|pluralize }} below.</p>{% endif %}\n') 591 t.append('{% if csrf_failed %}<p class="errornote">CSRF protection: Please re-submit.</p>{% endif %}\n') 591 592 for fieldset_name, options in admin_field_objs: 592 593 t.append('<fieldset class="module aligned %s">\n\n' % options.get('classes', '')) 593 594 if fieldset_name: … … 687 688 t.append('<li id="p{%% firstof %(x)s %%}"><span id="handlep{%% firstof %(x)s %%}">{{ object|truncatewords:"5" }}</span></li>' % \ 688 689 {'x': ' '.join(['object.%s' % o.pk.name for o in ordered_objects])}) 689 690 t.append('{% endfor %}</ul>{% endif %}\n') 691 t.append('{% load csrf %}{% csrf_token %}\n') 690 692 t.append('</form>\n</div>\n{% endblock %}') 691 693 return ''.join(t) 692 694 … … 759 761 t.append('{% endif %}') 760 762 return ''.join(t) 761 763 764 def csrf_token_check(request): 765 from django.models.auth import csrf 766 try: 767 token = csrf.get_object(token__exact = request.POST.get('csrf_token', ''), 768 select = {'user_id': request.user.id}) 769 except csrf.CsrfTokenDoesNotExist: 770 return False 771 token.delete() 772 return True 773 762 774 def add_stage(request, app_label, module_name, show_delete=False, form_url='', post_url='../', post_url_continue='../%s/', object_id_override=None): 763 775 mod, opts = _get_mod_opts(app_label, module_name) 764 776 if not request.user.has_perm(app_label + '.' + opts.get_add_permission()): 765 777 raise PermissionDenied 766 778 manipulator = mod.AddManipulator() 779 csrf_failed = False 767 780 if request.POST: 768 781 new_data = request.POST.copy() 769 782 if opts.has_field_type(meta.FileField): 770 783 new_data.update(request.FILES) 771 784 errors = manipulator.get_validation_errors(new_data) 772 if not errors and not request.POST.has_key("_preview"): 785 # Check the csrf_token 786 csrf_failed = not csrf_token_check(request) 787 if not errors and not csrf_failed and not request.POST.has_key("_preview"): 773 788 for f in opts.many_to_many: 774 789 if f.rel.raw_id_admin: 775 790 new_data.setlist(f.name, new_data[f.name].split(",")) … … 844 859 'title': 'Add %s' % opts.verbose_name, 845 860 "form": form, 846 861 "is_popup": request.REQUEST.has_key("_popup"), 862 "csrf_failed": csrf_failed, 847 863 }) 848 864 if object_id_override is not None: 849 865 c['object_id'] = object_id_override … … 864 880 raise Http404 865 881 866 882 inline_related_objects = opts.get_inline_related_objects() 883 csrf_failed = False 867 884 if request.POST: 868 885 new_data = request.POST.copy() 869 886 if opts.has_field_type(meta.FileField): 870 887 new_data.update(request.FILES) 871 888 872 889 errors = manipulator.get_validation_errors(new_data) 873 if not errors and not request.POST.has_key("_preview"): 890 # Check the csrf_token 891 csrf_failed = not csrf_token_check(request) 892 if not errors and not csrf_failed and not request.POST.has_key("_preview"): 874 893 for f in opts.many_to_many: 875 894 if f.rel.raw_id_admin: 876 895 new_data.setlist(f.name, new_data[f.name].split(",")) … … 969 988 "form": form, 970 989 'object_id': object_id, 971 990 'original': manipulator.original_object, 972 'is_popup' : request.REQUEST.has_key('_popup'), 991 'is_popup': request.REQUEST.has_key('_popup'), 992 'csrf_failed': csrf_failed, 973 993 }) 974 994 raw_template = _get_template(opts, app_label, change=True) 975 995 # return HttpResponse(raw_template, mimetype='text/plain') … … 1073 1093 deleted_objects = ['%s: <a href="../../%s/">%s</a>' % (capfirst(opts.verbose_name), object_id, strip_tags(repr(obj))), []] 1074 1094 perms_needed = sets.Set() 1075 1095 _get_deleted_objects(deleted_objects, perms_needed, request.user, obj, opts, 1) 1076 1077 if request.POST: # The user has already confirmed the deletion. 1096 csrf_failed = False 1097 if request.POST: 1098 csrf_failed = not csrf_token_check(request) 1099 if request.POST and not csrf_failed: # The user has already confirmed the deletion. 1078 1100 if perms_needed: 1079 1101 raise PermissionDenied 1080 1102 obj_repr = repr(obj) … … 1089 1111 "object": obj, 1090 1112 "deleted_objects": deleted_objects, 1091 1113 "perms_lacking": perms_needed, 1114 "csrf_failed": csrf_failed, 1092 1115 }) 1093 1116 return HttpResponse(t.render(c), mimetype='text/html; charset=utf-8') 1094 1117