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


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


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


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


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


    这种结果是由于我们在表单中使用了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载入地址

    而我就犯了不能取到的第三种错误。所以我们要吧原来的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

    以后我们会具体讨论这个问题的。

  • 相关阅读:
    .NET Core技术研究-HttpContext访问的正确姿势
    .NET 5 Preview 1的深度解读和跟进
    玩转VSCode-完整构建VSCode开发调试环境
    China .NET Conf 2019-.NET技术架构下的混沌工程实践
    如何做好开发自测
    .NetCore技术研究-.NET Core迁移前的准备工作
    .NetCore技术研究-一套代码同时支持.NET Framework和.NET Core
    .NetCore技术研究-ConfigurationManager在单元测试下的坑
    统一流控服务开源:基于.Net Core的流控服务
    计组:计算机为什么有反码补码?不列公式!
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5121370.html
Copyright © 2020-2023  润新知