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

2015-11-06 11:05:50 +08:00
 TakanashiAzusa

问题

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
6794 次点击
所在节点    JavaScript
26 条回复
kokdemo
2015-11-06 11:11:03 +08:00
可以啊, ajax 本质上就是一个 xhr 请求,和 form 的当然不一样了。

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

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

我这里没有说清楚,抱歉了。
yongzhong
2015-11-06 11:37:13 +08:00
ajax 在请求头里会有一个特殊的标识符,后台可以用来判断
TakanashiAzusa
2015-11-06 11:38:03 +08:00
@hcymk2 那个页面上,用 chrome 开发者工具的 console 里直接运行我那段 js 模拟 post 提交返回的页面和直接用他的表单提交得到的结果是不是一样的。
我就是不知道这个是怎么做到的。不知道是我前端的问题还是后台可以限制。。
TakanashiAzusa
2015-11-06 11:38:58 +08:00
@yongzhong 但是我这里贴出来的 header 里没有明显的字段差别啊。
TakanashiAzusa
2015-11-06 11:40:06 +08:00
@kokdemo 能问下是怎么做到的么?给个关键词就好。
我刚刚找了下大部分说的都是区分前端框架的 ajax ,但是那个是因为前端框架手动加了个字段。。
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
2015-11-06 11:46:43 +08:00
@br00k 我刚看了一下 ci 的代码,和你说的这个基本是一个意思
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
2015-11-06 11:47:29 +08:00
@yongzhong
@br00k

Ajax 的 X_REQUESTED_WITH 头是 Ajax 库加上去的。
如果是自己使用 XMLHttpRequest 实现,则没有这个头。
TakanashiAzusa
2015-11-06 11:48:38 +08:00
@br00k @kokdemo
但是这个文件头应该不是全部的 ajax 请求都有的。。我前面贴的原生 xhr 的 post 的 header 里并没有这个字段
TakanashiAzusa
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
2015-11-06 11:55:46 +08:00
@bertonzh 抱歉 v2 的回复提醒好像有点抽,前面 6 楼的回复没看到。我把 accept 改成一样的了,但是还是没什么效果。。
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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/234087

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX