前端提交表单数据的三种方式以及跨域实现

这里讲的是不刷新页面的三种方式:

方式一:xmlrequest,也即原生方式

 <input id="k1" name="k1">
    <input type="submit"  onclick="nativeSubmit()" id="submit">
<script>
        function nativeSubmit() {
            var k1_v=document.getElementById("k1").value
            var data={'k1':k1_v}
            data=JSON.stringify(data)
            var xhr_obj=new  XMLHttpRequest()
            xhr_obj.open("post","/test")
            xhr_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //request.body
            xhr_obj.send(data)
            xhr_obj.onreadystatechange=function () {
                if (xhr_obj.readyState == 4 && xhr_obj.status == 200) {
                        alert(xhr_obj.responseText);
                }
            }
         }
</script>

表单处理过程:收集数据-->发送数据-->接收数据处理

原生方式中,通过选择器收集标签的取值,在open函数中指定提交的方式和目标url,在send中发送post请求的数据(如果用get,则在open里面的url部分用?k=v的形式发送),回调函数则通过触发onreadystatechange事件在执行,readyState有多个值,对应数据处理的不同阶段,当等于4时则表示数据接收完毕

这里加了个:xhr_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //request.body

这里因为post请求默认放在body里面,只有加上这个头部,django才会把body的数据处理放到request.POST里面,ajax处理会有这部分,所以这里也设置

方式二:ajax

    <input id="k1" name="k1">
    <input type="submit"  id="submit">
    <script src="/static/js/jquery-3.5.1.min.js"> </script>
    <script>
        $("#submit").click(function () {
            var k1_v=$("#k1").val()
            var data={'k1':k1_v}
            $.ajax({
                type:"POST",
                url:"/test",
                data:data,
                success(arg){
                    alert(arg)
                }
            })

        })
</script>

ajax封装了原生的语法,使用更简单,缺点就是需要额外加载jquery文件,对于一些流量紧张的应用不适用

方式三:form+iframe标签

  <iframe id="ifr" name="iframe"   style="display: none"></iframe>
<form action="/test" method="POST" target="iframe">
    <input id="k1" name="k1" >
    <input type="submit"  onclick="ifr1()" id="submit">
</form>

<script>
function ifr1(){
        document.getElementById("ifr").onload=reload;
    }
 {# 这里为什么不直接在iframe标签那里绑定reload事件呢?#}
 {# 因为会报错,如果iframe放在script上面会报reload函数找不到,如果放在下面则document找不到 #}
 {# 这是iframe的特殊之处,原因待查明 #}
function reload() {
        var content = this.contentWindow.document.body.innerHTML;
        alert(content)

    }
</script>

form表单通过target(值即iframe的name的值)与iframe关联,参数的设定跟直接form表单提交一样,差别在于回调函数的返回值在iframe里面,iframe类似一个小Windows对象,值放在document的body里面

这里<input type="submit" onclick="ifr1()" id="submit">,click事件处理在submit之前,所以可以直接这么写

前面的例子都是对字符串进行处理,若需要对文件进行处理,则可以用FormData对象进行封装

 <input id="k1" type="file" name="k1">
    <input type="submit"  onclick="nativeSubmit()" id="submit">
<script>
        function nativeSubmit() {
            var k1_v=document.getElementById("k1").files[0]
            console.log(k1_v)
            var data=new FormData()
            data.append("k1",k1_v)
            var xhr_obj=new  XMLHttpRequest()
            xhr_obj.open("post","/test")
            xhr_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //request.body
            xhr_obj.send(data)
            xhr_obj.onreadystatechange=function () {
                if (xhr_obj.readyState == 4 && xhr_obj.status == 200) {
                        alert(xhr_obj.responseText);
                }
            }
         }
</script>
debug:

1.Refused to display 'http://127.0.0.1:8000/test' in a frame because it set 'X-Frame-Options' to 'deny'.

    原因:现代浏览器采用X-Frame-Options HTTP标头,该标头指示是否允许在框架或iframe中加载资源。如果响应包含标头值为的标头,SAMEORIGIN则浏览器将仅在请求源自同一站点的情况下将资源加载到框架中。如果将标头设置为,DENY则无论哪个站点发出请求,浏览器都将阻止资源加载到框架中。

解决方法有以下三种:

<1>注销掉

    'django.middleware.clickjacking.XFrameOptionsMiddleware'中间件

<2>处理函数前加上装饰器:

from django.views.decorators.clickjacking import xframe_options_exempt

@xframe_options_exempt

<3>在setting中设置:

    X_FRAME_OPTIONS = 'SAMEORIGIN'

2.jsonp和cors头部实现跨域

问题:当form提交请求时,有同源限制,比如我的网站是a.com,我提交请求也是向a.com提交,当我向b.com提交请求的的时候,因为浏览器会判断同源限制,会导致收到的数据不显示
例子:


   <button onclick="getvalue()">点击获取值</button>
    返回值是:<input id="k1" name="k1">
<script src="/static/js/jquery-3.5.1.min.js"> </script>
<script>
    function getvalue() {
        $.ajax({
            url:"http://127.0.0.1:9000/test1",
            type:"get",
            success(arg) {
            $("#k1").val(arg)
    }
        })
    }
</script>

报错:
前端提交表单数据的三种方式以及跨域实现

解决:

方式一:cors头部

最简单的是取消限制,服务端在响应请求的时候,在http头部加上:

Access-Control-Allow-Origin :*
客户端看到这个头部会取消同源限制

服务端代码:

def test1(request):
    ret=HttpResponse("hello")
    ret["Access-Control-Allow-Origin"]="*"
    return ret

方式二:jsonp

jsonp的原理在于利用其它可以跨域的标签,比如<script>、<img>等标签的src属性不受同源限制,jsonp就是动态创建这些标签,取得值后删除
<img>的src获取到数据后会渲染成图片,而在img标签中似乎没法获取图片的值,所以这里我用<script>标签

<script>标签的src获取到数值会以js的方式处理,所以如果我们服务端返回一个在前端已经定义的函数执行形式,比如func(),那么当客户端收到返回值就会执行对应函数,也就达到了回调函数的功能

前端代码:

 <button onclick="getvalue()">点击获取值</button>
    返回值是:<input id="k1" name="k1">
<script>
     var url="http://127.0.0.1:8000/test1"
    function getvalue() {
        var s_ele=document.createElement("script")
        s_ele.src=url
        document.body.appendChild(s_ele)
        document.body.removeChild(s_ele)
    }
    function func(arg) {
            document.getElementById('k1').value=arg

服务端代码:

def test1(request):
    ret=HttpResponse("func('hello')")
    ret["Content-Type"]="text/javascript"
    return ret

ajax的前端代码则更为简单,只要在dataType赋值jsonp,ajax默认就会以jsonp的形式跨域取值,代码如下:

 <button onclick="getvalue()">点击获取值</button>
    返回值是:<input id="k1" name="k1">
    <script src="/static/js/jquery-3.5.1.min.js"> </script>
<script>
    function getvalue() {
        $.ajax({
            url:"http://127.0.0.1:8000/test1",
            dataType:"jsonp"
        })
    }
    function func(arg) {
            $("#k1").val(arg)
    }
</script>

debug:

1.test:1 Refused to execute script from 'http://127.0.0.1:8000/test1' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

解决:HttpResponse返回设置头部:Content-Type;"text/javascript"

上一篇:内网安全4-Metasploit和Cobaltstrike内⽹域渗透


下一篇:CobaltStrike之信息收集模块System Profiler