Python+Django+SAE系列教程14-----使表单更安全

来源:互联网 发布:js时间选择控件 编辑:程序博客网 时间:2024/06/08 17:10

还记得我们上一章提到过的添加页面吗?


添加完以后我们注意一下地址栏:


表单里的数据赤裸裸的显示在了地址栏中,这时候如果我们修改一下内容


刷新,这样数据库里面就会又加入了一条数据,也就是说用户如果知道表单的结果页的连接,就可以不通过我们的表单,任意添加数据了,这样当然不是我们想要的结果。


这样的结果是因为我们在表单中使用了get的方式来传递数据,这时我们应该想到采用post的方法,postget更加安全,我们来修改一下模板页面,注意这里:



下面是表单模板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,在一定程度上保证了表单的安全。

下面的问题就是直接访问修改页面或者删除页面呢,如这样:

直接在浏览其中输入地址,就可以删除和打开修改页面了,这样太危险了。所有这就要用到我们在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.利用Jscriptlocation.href or location.replace()

4.在浏览器直接输入地址

5<%Response.Redirect%>

6<%Response.AddHeader%><meta http-equiv=refresh>转向

7.用XML加载地址

 

而我就犯了不能取到的第三种错误。所以我们要吧原来的按钮修改成为连接(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

以后我们会详细讨论这个问题的。

86 0