为什么用 ajax 模拟 form 表单提交返回页面总是和直接 submit 提交的不一样 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
TakanashiAzusa
V2EX    Javascript

为什么用 ajax 模拟 form 表单提交返回页面总是和直接 submit 提交的不一样

  •  
  •   TakanashiAzusa 2015-11-06 11:05:50 +08:00 7057 次点击
    这是一个创建于 3702 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题

    RT 。网站是这个:
    https://eq.wowow.co.jp/CGI/enq/engeki2015/index.cgi/conf/

    网站传输用的是multipart/form-data,不过我用 post 模拟提交的数据和 submit 格式是一样的。
    而且看了下两个的 request header 基本上也没差了,但是 respone 的 header 和页面就差了不少。后台没写过不清楚,看了下两个最大的区别应该是一个文档类型是document一个是xhr,想问下后台的话可以根据这个直接判定返回的页面吗?

    相关数据:

    我使用的代码:

    var data={ key:'conf', mem_flg:'', page:'1', back_page:'', '000021914':'ssd', '000021912':'男性', '000021913':'20 代', '000021911':'', '000021916':'sssd', '000021926':'dsds', '000021918':'dsdd', '000021920':'ads', '000021922':'adsds', '000021923':'', '000021924':'0001::同意する', '000021925':'0001::同意する', submit:'次 へ ' }; function sendData(data) { var XHR = new XMLHttpRequest(); var FD = new FormData(); for(name in data) { FD.append(name, data[name]); } XHR.addEventListener('load', function(event) { console.log('Yeah! Data sent and response loaded.'); }); XHR.addEventListener('error', function(event) { console.log('Oups! Something goes wrong.'); }); XHR.open('POST', 'https://eq.wowow.co.jp/CGI/enq/engeki2015/index.cgi/conf/'); XHR.setRequestHeader('Upgrade-Insecure-Requests', '1'); XHR.setRequestHeader('Cache-Control','max-age=0'); XHR.send(FD); } sendData(data) 

    submit 提交的 request header :

    POST /CGI/enq/engeki2015/index.cgi/conf/ HTTP/1.1 Host: eq.wowow.co.jp Connection: keep-alive Content-Length: 1778 Cache-Control: max-age=0 Origin: https://eq.wowow.co.jp Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5LSRJwQdceXFo8uo Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 X-FirePHP-Version: 0.0.6 Referer: https://eq.wowow.co.jp/CGI/enq/engeki2015/index.cgi/conf/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4 Cookie: wowow2_MGSID_AuthTicket=57d35173edd644dac7cca0ada9fe586a2b874b7a; wowow2_MGSID=0117130a152e480144668844800011862; enq_plus_000002528=6645110a152e550144677804300003180 

    submit 提交后返回的 respone header :

    HTTP/1.1 200 OK Date: Fri, 06 Nov 2015 02:48:44 GMT Server: Apache Pragma: no-cache Cache-Control: no-store, no-cache, post-check=0, pre-check=0 Expires: -1 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html;charset= 

    ajax post 模拟的 request header :

    POST /CGI/enq/engeki2015/index.cgi/conf/ HTTP/1.1 Host: eq.wowow.co.jp Connection: keep-alive Content-Length: 1754 Origin: https://eq.wowow.co.jp Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryj73JdouNDpXuT6ep Cache-Control: max-age=0 X-FirePHP-Version: 0.0.6 Accept: */* Referer: https://eq.wowow.co.jp/CGI/enq/engeki2015/index.cgi/conf/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4 Cookie: wowow2_MGSID_AuthTicket=57d35173edd644dac7cca0ada9fe586a2b874b7a; wowow2_MGSID=0117130a152e480144668844800011862; enq_plus_000002528=6645110a152e550144677804300003180 

    ajax 提交后返回的 respone header :

    HTTP/1.1 200 OK Date: Fri, 06 Nov 2015 02:49:37 GMT Server: Apache Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html;charset= 
    第 1 条附言    2015-11-06 12:18:13 +08:00

    感谢 @bertonzh 的检查,是我傻逼了,发送的字段内容复制错了。。这个问题算是解决了。。

    不过为了不让各位的心思白费,扩展下问题吧:
    如果前端不配合的情况下,后台可以直接判断出来数据是 form 表单的 submit 提交还是利用 ajax 的 post 提交的吗?

    26 条回复    2015-11-06 12:19:04 +08:00
    kokdemo
        1
    kokdemo  
       2015-11-06 11:11:03 +08:00   1
    可以啊, ajax 本质上就一个 xhr 请求,和 form 的当然不一样了。

    有一些框架里面都可以判断请求是不是 ajax 的,然后返回不一样的内容。
    TakanashiAzusa
        2
    TakanashiAzusa  
    OP
       2015-11-06 11:13:41 +08:00
    @kokdemo 所以其实就是后台一旦接收到是 xhr 请求的话就直接返回 a 页面,如果是 form 提交就 b 页面这样么?因为这里的 form 和 xhr 都是 post 的,我以为对后台来说没什么区别呢。。
    cxe2v
        3
    cxe2v  
       2015-11-06 11:16:16 +08:00
    其实可以 submit 和 ajax 提交的地址不一样,就能各自返回不同的东西了
    TakanashiAzusa
        4
    TakanashiAzusa  
    OP
       2015-11-06 11:17:14 +08:00
    @cxe2v 不不不,我现在不是这个意思,而是我想让 post 和 submit 的返回结果一样,但是不管怎么试都试不出来,不知道是我前端哪里疏漏了还是后台他们可以直接判断来源。。
    TakanashiAzusa
        5
    TakanashiAzusa  
    OP
       2015-11-06 11:24:28 +08:00
    @kokdemo 我查了下很多资料里都提到了“ HTTP_X_REQUESTED_WITH ”这个 header 头,但是这个头貌似是要前端加上去的,而原生的是不带这个头的,所以想问下在前端不配合的情况下,后台可以直接筛选出来这两种方式么
    bertonzh
        6
    bertonzh  
       2015-11-06 11:33:22 +08:00   1
    @kokdemo XHR 和表单提交本质上都是 HTTP 请求,怎么就不一样了?

    感觉是 Accpet 的问题。楼主可以先试试修改。不过有一些请求头在 XHR 里面是修改不了的,可以考虑用代理工具 charles 拦截请求,在 charles 里面修改。
    hcymk2
        7
    hcymk2  
       2015-11-06 11:33:46 +08:00
    什么是 post 和 submit 返回的结果不一样?你的 js 是写在哪里的?
    kokdemo
        8
    kokdemo  
       2015-11-06 11:35:06 +08:00
    @bertonzh 都是 http 请求,但是服务器可以分辨出来是 xhr 还是普通的表单提交。

    我这里没有说清楚,抱歉了。
    yongzhong
        9
    yongzhong  
       2015-11-06 11:37:13 +08:00
    ajax 在请求头里会有一个特殊的标识符,后台可以用来判断
    TakanashiAzusa
        10
    TakanashiAzusa  
    OP
       2015-11-06 11:38:03 +08:00
    @hcymk2 那个页面上,用 chrome 开发者工具的 console 里直接运行我那段 js 模拟 post 提交返回的页面和直接用他的表单提交得到的结果是不是一样的。
    我就是不知道这个是怎么做到的。不知道是我前端的问题还是后台可以限制。。
    TakanashiAzusa
        11
    TakanashiAzusa  
    OP
       2015-11-06 11:38:58 +08:00
    @yongzhong 但是我这里贴出来的 header 里没有明显的字段差别啊。
    TakanashiAzusa
        12
    TakanashiAzusa  
    OP
       2015-11-06 11:40:06 +08:00
    @kokdemo 能问下是怎么做到的么?给个关键词就好。
    我刚刚找了下大部分说的都是区分前端框架的 ajax ,但是那个是因为前端框架手动加了个字段。。
    br00k
        13
    br00k  
       2015-11-06 11:43:51 +08:00
    后台可以根据 HTTP_X_REQUESTED_WITH 判断是否为 AJAX 方式提交。
    这个是 TP 的判断方法。
    protected function isAjax() {
    if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) ) {
    if('xmlhttprequest' == strtolower($_SERVER['HTTP_X_REQUESTED_WITH']))
    return true;
    }
    if(!empty($_POST[C('VAR_AJAX_SUBMIT')]) || !empty($_GET[C('VAR_AJAX_SUBMIT')]))
    // 判断 Ajax 方式提交
    return true;
    return false;
    }
    kokdemo
        14
    kokdemo  
       2015-11-06 11:46:43 +08:00
    @br00k 我刚看了一下 ci 的代码,和你说的这个基本是一个意思
    icedx
        15
    icedx  
       2015-11-06 11:47:18 +08:00
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

    这个不一样啊
    bertonzh
        16
    bertonzh  
       2015-11-06 11:47:29 +08:00   1
    @yongzhong
    @br00k

    Ajax 的 X_REQUESTED_WITH 头是 Ajax 库加上去的。
    如果是自己使用 XMLHttpRequest 实现,则没有这个头。
    TakanashiAzusa
        17
    TakanashiAzusa  
    OP
       2015-11-06 11:48:38 +08:00
    @br00k @kokdemo
    但是这个文件头应该不是全部的 ajax 请求都有的。。我前面贴的原生 xhr 的 post 的 header 里并没有这个字段
    TakanashiAzusa
        18
    TakanashiAzusa  
    OP
       2015-11-06 11:54:15 +08:00
    @icedx 我能看出来的区别也就这里面了。。但是`Accept`这个字段前端是可以改的。我那里的 js 代码里只要加一句
    “ XHR.setRequestHeader('Accept','text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8');”
    就可以改掉了。。
    而且我刚刚加了试一下和之前的也没啥区别,一样是不同的页面
    TakanashiAzusa
        19
    TakanashiAzusa  
    OP
       2015-11-06 11:55:46 +08:00
    @bertonzh 抱歉 v2 的回复提醒好像有点抽,前面 6 楼的回复没看到。我把 accept 改成一样的了,但是还是没什么效果。。
    br00k
        20
    br00k  
       2015-11-06 11:59:26 +08:00
    @TakanashiAzusa
    我试了,是有的。在域名下面控制台输入。
    $.ajax({
    contentType:"multipart/form-data"
    })

    Accept:*/*
    Accept-Encoding:gzip, deflate, sdch
    Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
    Cache-Control:no-cache
    Connection:keep-alive
    Content-Type:multipart/form-data
    Cookie:enq_plus_000002528=8597130a152e540144678235400000449
    Host:eq.wowow.co.jp
    Pragma:no-cache
    Referer:https://eq.wowow.co.jp/CGI/enq/engeki2015/index.cgi/conf/
    User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36
    X-Requested-With:XMLHttpRequest
    TakanashiAzusa
        21
    TakanashiAzusa  
    OP
       2015-11-06 12:03:16 +08:00
    @br00k $.ajax 是框架(jq 或者 zepto 之类的)封装的 xhr 不是原生的 xmlHttpRequest 。。我前面正文里贴过原生的 xhr 代码,你可以用那个试试看。
    bertonzh
        22
    bertonzh  
       2015-11-06 12:10:56 +08:00
    @TakanashiAzusa
    楼主仔细检查下你的表单内容。

    这三个字段有问题:
    -------
    '000021912':'男性',
    '000021913':'20 代',
    '000021911':'',
    bertonzh
        23
    bertonzh  
       2015-11-06 12:12:22 +08:00
    这是原始表单:

    0001::男性
    ------WebKitFormBoundaryWm2VeBo2patOxQ5k
    Content-Disposition: form-data; name="000021913"

    0002::20 代
    ------WebKitFormBoundaryWm2VeBo2patOxQ5k
    Content-Disposition: form-data; name="000021911"

    0007::
    ------WebKitFormBoundaryWm2VeBo2patOxQ5k
    Content-Disposition: form-data; name="000021916"
    TakanashiAzusa
        24
    TakanashiAzusa  
    OP
       2015-11-06 12:15:11 +08:00
    @bertonzh 我去还真是- -是我傻逼了。。不好意思。。
    bertonzh
        25
    bertonzh  
       2015-11-06 12:15:29 +08:00   1
    前面一条 boundary 和值的前后顺序有问题。值也被我改错了。楼主不要直接复制粘贴。
    TakanashiAzusa
        26
    TakanashiAzusa  
    OP
       2015-11-06 12:19:04 +08:00
    @bertonzh 嗯,我刚刚改了下已经成功了。谢谢。。可能昨天要复制的字段比较多所以后面只看了 key 的值, name 里的想当然了。多谢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4385 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 01:05 PVG 09:05 LAX 17:05 JFK 20:05
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86