`
lbxhappy
  • 浏览: 309143 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

利用decorator实现Django表单防重复提交

阅读更多

背景:

 

   我的用例中不可出现重复的记录,如:下订单,用户填好表单然后Submit,当用户网速较慢时,很可能会习惯性的刷新当前页,而刷新操作会导致再次POST,此时若不加判断直接入库必然导致用户后台增加N个订单。

 

 解决思路:

 

   Step 1:首先我们在进入表单填写页面时,对该页面(或view吧)随机生成一个校验字符串并存放于Session中,在页面form中新增一个hidden input来存放,以便提交时一起POST到服务器端;

   Step 2:当POST时,服务器端将收到的校验串与Session中对应值比对,若相同则正常提交,否则跳转至指定的错误提示页面;需要注意的是当比对成功后, 必须立即将该Session的值设置为空,这样才可保证页面再次POST时表单中的校验串就无法于Session中的空值比对成功。

 

 实现:

   为了方便使用,我们将上述思路写成一个decorator(装饰器). 当然也是为了符合DRY嘛;代码很简单就看中间那几行,需注意唯一的一个参数page_key,为了不跟多个表单页面发生Session key冲突。(补充一点:必须将表单填写页面的view同时使用@never_cache装饰,因为django默认将所有view都做缓存,当再次进入表单页时,就不会重新生成随机串,导致校验无故失败。。。

 

# coding:utf-8
 
try :
     from functools import wraps
except ImportError:
     from django.utils.functional import wraps  # Python 2.4 fallback.
import random
from django.conf import settings
from django.utils.decorators import available_attrs
from django.utils.hashcompat import md5_constructor
 
if hasattr (random, 'SystemRandom' ):
     randrange = random.SystemRandom().randrange
else :
     randrange = random.randrange
_MAX_CSRF_KEY = 18446744073709551616L      # 2 << 63
 
def _get_new_submit_key():
     return md5_constructor( "%s%s" % (randrange( 0 , _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest()
 
def anti_resubmit(page_key = ''):
     def decorator(view_func):
         @wraps (view_func, assigned = available_attrs(view_func))
         def _wrapped_view(request, * args, * * kwargs):
             if request.method = = 'GET' :
                 request.session[ '%s_submit' % page_key] = _get_new_submit_key()
                 print 'session:' + request.session.get( '%s_submit' % page_key)
             elif request.method = = 'POST' :
                 old_key = request.session.get( '%s_submit' % page_key, '')
                 if old_key = = '':
                     from django.http import HttpResponseRedirect
                     return HttpResponseRedirect( '/page_expir' )
                 request.session[ '%s_submit' % page_key] = ''
             return view_func(request, * args, * * kwargs)
         return _wrapped_view
     return decorator

 

 

   使用示例:

1  @anti_resubmit(page_key = ' your_view ' )
2    def  your_view(request):
3       ''' 若是表单填写页和POST的view不是同一个,則需在两个view上都使用anti_resubmit装饰器 '''
4       pass   # 您可别跟着pass噢
分享到:
评论

相关推荐

    DJANGOPOST提交问题解决2.pdf

    Django的CSRF保护机制通过在表单提交时检查一个由服务器生成的随机令牌来防止这种攻击。 在尝试解决这个问题时,开发者可能首先想到的是在`settings.py`的`MIDDLEWARE_CLASSES`中添加`'django.middleware.csrf....

    中文版django_book1

    - Django表单(Form)的创建与渲染 - 表单数据的验证与处理 - 表单类的使用和自定义 8. **第八章 高级视图和URLconfs**: - 视图函数与类视图的使用 - 高级URL模式和反向解析 - 视图装饰器(Decorator)的应用 9...

    Django使用中间键实现csrf认证详解

    在Django框架中,CSRF(Cross Site Request Forgery,跨站请求伪造)是一种重要的安全机制,用于防止恶意第三方在用户浏览器中冒充用户发送非预期的请求。Django通过中间件`django.middleware.csrf....

    Python库 | django_budget_backend-0.2-py3-none-any.whl

    为了充分利用`django_budget_backend`,开发者需要熟悉Django框架的基本用法,了解如何创建和配置应用,以及如何使用模型、视图、模板等核心概念。同时,阅读库的文档和源代码是十分必要的,这有助于理解库的具体...

    Django面试题.pdf_python面试

    Django通过method_decorator来支持将函数装饰器转换为方法装饰器,实现为类中的方法添加额外功能的目的。 **数据库迁移** Django默认使用SQLite数据库,但在生产环境中,我们通常会切换到更强大的数据库系统,如...

    Django CSRF跨站请求伪造防护过程解析

    CSRF(跨站请求伪造)是一种常见的网络安全威胁,攻击者利用用户的已登录状态,在用户不知情的情况下,通过恶意网站发起对受害者的合法网站的请求,执行非用户意愿的操作。Django框架提供了一套强大的CSRF防护机制,...

    DjangoCSRF认证的几种解决方案.docx

    - **防御机制**:为了防止此类攻击,Django提供了多种防御机制。主要包括Double Submit Cookie和Synchronizer Token等方法。 #### 二、Django CSRF防护机制 1. **Double Submit Cookie** - **工作原理**:在...

    django写用户登录判定并跳转制定页面的实例

    使用Django可以轻松实现数据库的交互、表单处理、用户认证和会话管理等功能。 在实现用户登录状态的判定时,Django提供了一个内置的用户认证系统,可以很方便地处理用户登录与登出等逻辑。Django使用session(会话...

    Django CSRF认证的几种解决方案

    2. **前端表单中增加CSRF信息**:在前端表单中手动添加`csrf_token`字段,可以在提交表单时确保包含正确的CSRF token。这种方式适用于普通的HTML表单提交,但不适合AJAX请求。 - **示例代码**: ```html {% ...

    Django中login_required装饰器的深入介绍

    `login_required`装饰器便是Django内置的一种强大的工具,它可以帮助开发者轻松地实现这一目标。本文将深入探讨`login_required`装饰器的工作原理、使用方法以及几个实际的应用场景。 #### LOGIN_REQUIRED装饰器...

    Python网页登录模板

    此外,还可以利用Django的中间件(Middleware)和装饰器(Decorator)来增强功能。 总之,这个Python网页登录模板结合了Django的强大力量,Pywebio的交互性以及requests的网络通信能力,为Web应用开发提供了一个...

    Python基础面试题

    4. Django表单验证:使用`Form.is_valid()`来验证表单提交的数据是否符合预先定义的格式。 5. Django服务器架构:Nginx负责静态文件服务和反向代理,uWSGI作为应用服务器处理Python应用,Django则是Web框架。三者...

    值得收藏的10道python 面试题

    这意味着Django在标准库中提供了许多开箱即用的功能,如ORM(对象关系映射)系统、模板引擎、身份验证和授权系统、表单处理、URL路由、数据库迁移工具等。这种全面的特性集合使得开发者能够快速构建复杂的Web应用,...

Global site tag (gtag.js) - Google Analytics