这让我疯了。我想提供一个.apk
文件供下载。我测试过的所有浏览器都会毫无问题地下载我的文件。除了android中的内置浏览器。出于某种奇怪的原因,它将重复对资源的请求。使用BurpSuite我发现apk文件传输完美无缺。我代理文件,但我立即发送标题,使用curl我可以确认标题已发送,内容开始在下面传输。我将我的标题与threema.ch
发送的标题进行了比较,这些标题完美无缺。
这些标题由我的应用程序发送:
HTTP/1.1 200 OK
Date: Sat, 16 Aug 2014 16:41:01 GMT
Server: Apache/2.4.7
Content-Disposition: attachment; filename="test.apk"
Content-Type: application/vnd.android.package-archive
Transfer-Encoding: Chunked
这些标题由Threema发送:
HTTP/1.1 200 OK
Server: nginx
Date: Sat, 16 Aug 2014 17:49:10 GMT
Content-Type: application/vnd.android.package-archive
Content-Length: 14146751
Connection: keep-alive
Content-Disposition: attachment; filename="Threema-1.63.apk"
Strict-Transport-Security: max-age=31536000; includeSubdomains
我首先通过iframe加载了该文件。目前我正在使用HTTP重定向将浏览器重定向到下载。我从不同的子域提供文件。但我也尝试从同一个域提供文件并使用html链接。
这些是客户端发送的标头。第一:
GET /download/download/NlnMhaeXmcjSosfqRTcG8YdxQgQGSxTWQeE10-GrH4U HTTP/1.1
Host: l.dl.test
Proxy-Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Safari/537.36
Referer: http://l.google/device/deviceid/351cd7c24f637eb5?token=6Xf3nJIIMIa4toKrpTqgDGFjAKzeBBoaeduMmcIMeGY
Accept-Encoding: gzip,deflate
Accept-Language: de-DE,en-US;q=0.8
X-Requested-With: com.android.browser
然后(大约20年后):
GET /download/download/NlnMhaeXmcjSosfqRTcG8YdxQgQGSxTWQeE10-GrH4U HTTP/1.1
User-Agent: Mozilla/5.0 (Linux; Android 4.4.4; Nexus 7 Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Safari/537.36
Referer:
cookie:
Accept-Encoding: identity
Host: l.dl.test
Connection: Keep-Alive
我正在生成一次性使用的下载ID。第二个请求将失败,因为在第一个请求后,id变为无效。如果我允许第二次尝试下载文件,则下载有效。
可能是android浏览器在第一次尝试时想要压缩内容,如果它获得了身份内容,它将使用Accept-Encoding身份进行第二次尝试?我也试过没有运气设置Content-Encoding: identity
。
解决方法: 我没有发送.apk两次的唯一方法就是使用这个非常愚蠢(并且容易出错)的解决方法:
header("Content-Disposition: attachment; filename=\"test.apk\"");
header('Content-Type: application/vnd.android.package-archive');
// Ugly workaround for bug in built-in android browser.
if (
isset($_SERVER['HTTP_X_REQUESTED_WITH'])
&& ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'com.android.browser')
&& isset($_SERVER['HTTP_ACCEPT_ENCODING'])
&& (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'identity') === FALSE)
) {
// The built-in android browser will make two requests for the apk
// file, one with Accept-Encoding gzip and deflate and one with
// Accept-Encoding identity. But it will only serve the second request
// with Accept encoding identity. So stop the first request.
// If the first request is shown, the workaround didn't work.
die ("Oh no! I'm sorry. The built-in android browser has a nasty bug."
. " It's hard to work around. If you see this the workaround failed."
. " Please try downloading with a different browser.");
}