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 · 6778 次点击
    这是一个创建于 3312 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题

    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=UTF-8
    

    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=UTF-8
    
    第 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   ·   实用小工具   ·   927 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:50 · PVG 05:50 · LAX 13:50 · JFK 16:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.