Python+Django+SAE系列教程14-----使表单更安全
还记得我们上一章提到过的加入页面吗?
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVtZW5nMTk4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
加入完以后我们注意一下地址栏:
表单里的数据赤裸裸的显示在了地址栏中,这时候假设我们改动一下内容
刷新,这样数据库里面就会又加入了一条数据,也就是说用户假设知道表单的结果页的连接,就能够不通过我们的表单。随意加入数据了,这样当然不是我们想要的结果。
这种结果是由于我们在表单中使用了get的方式来传递数据,这时我们应该想到採用post的方法,post比get更加安全,我们来改动一下模板页面,注意这里:
以下是表单模板Classroom_Add.html的代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>数据库操作简单表的加入</title>
</head>
<body>
<h1>这里是Classroom的加入页面</h1>
{% if error %}
<p style="color: red;">请输入班级名称和导师姓名</p>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<table border="1" cellpadding="10">
<tr>
<td align="center">项目</td>
<td align="center">内容</td>
</tr>
<tr>
<td align="right">班级名称:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td align="right">导师姓名:</td>
<td><input type="text" name="tutor"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="加入"></td>
</tr>
</table>
</form> </body>
</html>
把get方法改动为post后,我们当然也要改动一下视图,之前的get方法是这种:
def ClassroonAdd(request):
if 'name' in request.GET and request.GET['name'] and 'tutor' in request.GET and request.GET['tutor']:
name = request.GET['name']
tutor = request.GET['tutor']
c = ClassRoom(name=name,tutor=tutor)
c.save()
return render_to_response('person/Classroom_Add_results.html',
{'name': name})
else:
return render_to_response('person/Classroom_Add.html', {'error': True})
改动以后的pose方法是这种 :
def ClassroonAdd(request):
if request.POST.has_key('name') and request.POST.has_key('tutor') :
name = request.POST['name']
tutor = request.POST['tutor']
c = ClassRoom(name=name,tutor=tutor)
c.save() return render_to_response('person/Classroom_Add_results.html',
{'name': name},context_instance=RequestContext(request))
else:
return render_to_response('person/Classroom_Add.html', {'error': True},context_instance=RequestContext(request))
这时候我们在来測试一下:
地址栏里面的參数不见了!
我们在前一节讲的样例中另一个表单:就是改动页面。我们使用同样的方法来进行改动。改造Classroom_Modify.html模板:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>数据库操作简单表的改动</title>
</head>
<body>
<h1>这里是Classroom--{{name}}的改动页面</h1>
{% if error %}
<p style="color: red;">请输入班级名称和导师姓名</p>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<table border="1" cellpadding="10">
<tr>
<td align="center">项目</td>
<td align="center">内容</td>
</tr>
<tr>
<td align="right">班级名称:</td>
<td><input type="text" name="name" value="{{name}}"></td>
</tr>
<tr>
<td align="right">导师姓名:</td>
<td><input type="text" name="tutor" value="{{tutor}}"></td>
</tr>
<tr>
<td colspan="2">
<input type="hidden" name="id" value="{{id}}">
<input type="submit" value="改动">
<input type="button" value="返回" onClick="location.href='../../list'">
</td>
</tr>
</table>
</form>
</body>
</html>
改动视图页面:
def ClassroonModify(request,id1):
cursor=connection.cursor()
Classroon=ClassRoom.objects.get(id=id1)
old_name = Classroon.name
old_tutor = Classroon.tutor
cursor.close() if request.POST.has_key('name') and request.POST.has_key('tutor') :
new_name = request.POST['name']
new_tutor = request.POST['tutor']
Classroon.name=new_name
Classroon.tutor=new_tutor
Classroon.save()
return render_to_response('person/Classroom_Modify_results.html',
{'old_name': old_name,'old_tutor':old_tutor,'new_name':new_name,'new_tutor':new_tutor},context_instance=RequestContext(request))
else:
return render_to_response('person/Classroom_Modify.html', {'error': True,'id':id1,'name':old_name,'tutor':old_tutor},context_instance=RequestContext(request))
完毕。这样我们就把曾经的get方法改动成了post,在一定程度上保证了表单的安全。
以下的问题就是直接訪问改动页面或者删除页面呢,如这样:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVtZW5nMTk4MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
直接在浏览当中输入地址,就能够删除和打开改动页面了。这样太危急了。全部这就要用到我们在11章 的样例http://blog.csdn.net/hemeng1980/article/details/25239713中的GetHTTP_REFERER了。只是须要注意的是一下情况:
一、可以取到HTTP_REFERER的情况为下面几种:
1.直接用<a href>
2.用Submit或<input type=image>提交的表单(POST or GET)
3.使用Jscript提交的表单(POST or GET)
二、不能取到的情况有下面几种:
1.从收藏夹链接
2.单击”主页”或者自己定义的地址
3.利用Jscript的location.href or location.replace()
4.在浏览器直接输入地址
5.<%Response.Redirect%>
6.<%Response.AddHeader%>或<meta http-equiv=refresh>转向
7.用XML载入地址
而我就犯了不能取到的第三种错误。所以我们要吧原来的button改动成为连接(A标签)。改动Classroom_List.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>数据库操作简单表的加入</title>
</head>
<body>
<h1>这里是Classroom的管理页面</h1>
<table border="1" cellpadding="10">
<tr>
<td align="center">序号</td>
<td align="center">班级名称</td>
<td align="center">导师姓名</td>
<td align="center">操作</td>
</tr>
{% for myclass in ClassroonList%}
<tr>
<td align="right">{{ myclass.id }}</td>
<td align="right">{{ myclass.name }}</td>
<td align="right">{{ myclass.tutor }}</td>
<td align="right">
<a href="../modify/{{ myclass.id }}">改动</a>
<a href="../delete/{{ myclass.id }}">删除</a> </td>
</tr>
{% endfor %}
</table>
</body>
</html>
接下来我们改动一下视图:
def ClassroonModify(request,id1):
    GetHost=request.get_host()
    try:
        GetHTTP_REFERER = request.META['HTTP_REFERER']
    except KeyError:
        GetHTTP_REFERER = 'unknown'
    if GetHTTP_REFERER!='unknown' and GetHTTP_REFERER.find(GetHost)>0:
        cursor=connection.cursor()
        Classroon=ClassRoom.objects.get(id=id1)
        old_name = Classroon.name
        old_tutor = Classroon.tutor
        cursor.close()
        if request.POST.has_key('name')  and request.POST.has_key('tutor') :
            new_name = request.POST['name']
            new_tutor = request.POST['tutor']
            Classroon.name=new_name
            Classroon.tutor=new_tutor
            Classroon.save()
            return render_to_response('person/Classroom_Modify_results.html',
                {'old_name': old_name,'old_tutor':old_tutor,'new_name':new_name,'new_tutor':new_tutor},context_instance=RequestContext(request))
        else:
            return render_to_response('person/Classroom_Modify.html', {'error': True,'id':id1,'name':old_name,'tutor':old_tutor},context_instance=RequestContext(request))
    else:
        return render_to_response('person/Error.html')
不要忘了加入一个Error.html':
<html>
<head>
<title>查询用户结果页</title>
</head>
<body>
<table border="1" cellpadding="5"><tr>
<td>非法操作</td></tr>
<tr>
<td><a href="http://127.0.0.1:8000/ClassRoom/list/">点击返回</a></td>
</tr>
</table>
</body>
</html>
依照相同的方法改动一下删除功能:
def ClassroonDelete(request,id1):
    GetHost=request.get_host()
    try:
        GetHTTP_REFERER = request.META['HTTP_REFERER']
    except KeyError:
        GetHTTP_REFERER = 'unknown'
    if GetHTTP_REFERER!='unknown' and GetHTTP_REFERER.find(GetHost)>0:
        cursor=connection.cursor()
        Classroon=ClassRoom.objects.get(id=id1)
        old_name = Classroon.name
        Classroon.delete()
        ClassroonList=ClassRoom.objects.all()
        cursor.close()
        return render_to_response('person/Classroom_Delete_results.html',{'name':old_name})
    else:
        return render_to_response('person/Error.html')
我们做一下測试假设这时候直接输入网址:http://127.0.0.1:8000/ClassRoom/modify/48/
就会看到:
这样我们有保护了删除和改动页面的安全性。
最后另一个问题,假设加入后怎样防止刷新表单,这个功能眼下我们还没有解说到Session。先留一个伏笔把,假设对session了解的人,能够先參考这个试试 :
http://www.cnblogs.com/ken-zhang/archive/2010/12/25/1916437.html
以后我们会具体讨论这个问题的。
Python+Django+SAE系列教程14-----使表单更安全的更多相关文章
- Python+Django+SAE系列教程17-----authauth (认证与授权)系统1
		通过session,我们能够在多次浏览器请求中保持数据,接下来的部分就是用session来处理用户登录了. 当然,不能仅凭用户的一面之词,我们就相信,所以我们须要认证. 当然了,Django 也提供了 ... 
- Python+Django+SAE系列教程11-----request/pose/get/表单
		表单request,post,get 首先我们来看看Request对象,在这个对象中包括了一些实用的信息,学过B/S开发的人来说这并不陌生,我们来看看在Django中是怎样实现的: 属性/方法 说明 ... 
- Python+Django+SAE系列教程13-----MySQL记录的添\删\改
		建立了数据库后,我们就来做一个简单的表(person_classroom)的加入.删除.改动的操作. 首先我们建立一个加入的页面的模板Classroom_Add.html(加入的表单)并把它放在Bid ... 
- Python+Django+SAE系列教程15-----输出非HTML内容(图片/PDF)
		一个Django视图函数 必须 接受一个HttpRequest 实例作为它的第一个參数 返回一个HttpResponse 实例 从一个视图返回一个非HTML 内容的关键是在构造一个 HttpRespo ... 
- Python+Django+SAE系列教程16-----cookie&session
		本章我们来解说cookie和session ,这两个东西相信大家一定不陌生,概念就不多讲了,我们直接来看其使用方法,首先是cookie,我们在view中加入三个视图,一个是显示cookie的,一个是设 ... 
- Python+Django+SAE系列教程12-----配置MySQL数据库
		由于SAE上支持的是Mysql,首先我们要在本地配置一个Mysql的环境 ,我在网上找到MySQL-python-1.2.4b4.win32-py2.7.exe,并双击 安装 选择典型安装 安装结束后 ... 
- Python+Django+SAE系列教程9-----Django的视图和URL
		第三.四.五章介绍的就是Django中MVC的视图.模板.模型了. 首先来看视图(view),在用Django生成的站点目录中,创建一个view.py文件,这个文件開始是空的.然后我们输入下面内容: ... 
- Python+Django+SAE系列教程10-----Django模板
		在本章中,我们开始模板,在前面的章节,您可能已经注意到,我们回到文本的方式有点特别的示例视图. 那.HTML直接在硬编码 Python 其中代码. 这的确是一个小BT. def current_dat ... 
- Python+Django+SAE系列教程6-----本地配置Django
		前五章.我们介绍了Python的语法,本章開始介绍Django. Python的Web框架有非常多,有Django.web2py.tornado.web.py等.我们这里选 则Django.至于这些框 ... 
随机推荐
- 2014年国内经常使用移动client推送服务介绍和比較
			经过5年移动互联网的迅速发展,如今推送服务方面国内已经出现了非常多产品,比如极光推送,个推,一推,百度推送,友盟推送等,我们在选择推送服务时,首先排除了付费的推送服务,重点调查了免费的推送服务. ... 
- 图示CCScrollView的相关概念
			(转载请注明原文地址:http://blog.csdn.net/while0/article/details/11527899) 见下图: 1)设置ScrollView的视口大小的函数是:setVie ... 
- Swift - 制作一个录音机(声音的录制与播放)
			1,技术介绍 (1)AVFoundation.framework框架提供了AVAudioRecorder类.它可以实现录音功能. (2)而使用该框架的AVAudioPlayer类,可以实现声音的播放. ... 
- linux命令: sort
			参考 linux sort 命令详解 http://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html 1 sort的工作原理 sort将文 ... 
- bootbox api
			bootbox是boostrap集成的弹窗,基本能完成后台系统的需求,下面是一些使用方法 1.bootbox.alert bootbox.alert使用方法主要有三种 直接传内容 bootbox.al ... 
- Delphi中关于Rtti的一些操作(一)
			function TForm1.ShowMethodAddress(aObj: TDerived; const sData: String) : Pointer;var aPtr : Pointer ... 
- JavaScript 进阶(五)易混淆概念null vs undefined, == vs ===, string vs String
			先看一段代码 var foo = {} foo.a = null alert(foo.a == null) //true alert(foo.a === undefined) //false ... 
- codility上的问题(18) Rho 2012
			从正整数1开始,产生一个数列,数列中的每个数是之前出现过的任意两个数的和(可以相等),问产生正整数A,需要的数列长度至少是多少?返回这样一个最短的序列. 例如A=42 可以这样[1, 2, 3, 6, ... 
- grails一对一关联关系
			一对一关联关系开发中用的没有一对多那么广泛.可是我认为掌握以下还是有必要的.一对一关联关系有一张表存在外键,引用的通常是主表的主键.grails也对一对一关联关系提供了非常好的支持.配置也是简单的不得 ... 
- 棋盘问题 简单搜索DFS
			Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子 ... 
