我在 Windows 11 上开发了一个基于 Netty 的 HTTP/HTTPS 代理服务器(v4.1.x),目标是在 MuMu 模拟器(Android)上抓取一个特定 Flutter 应用的网络请求中的 Cookie。该应用使用索尼的第三方登录流程(点击登录后弹出索尼WebView登录,登录成功后WebView关闭,App获取凭证完成登录)。
我的设置:
将 MuMu 模拟器的全局 HTTP 和 HTTPS 代理设置为我的主机 IP 地址 192.168.1.108 和端口 8081。
为了捕获 Flutter App 可能通过 IP 地址进行的直接连接,我使用 iptables 规则(在模拟器内部?或者在主机上?请确认iptables设置位置)将所有来自模拟器的 IP 流量(非特定端口)重定向到 192.168.1.108:8081。
我的 Netty 代理成功处理了模拟器上普通的 HTTP/HTTPS 浏览流量(验证过)。
对比了登录过程中的关键响应:当 Netty 代理打开时,App 最终会收到一个 302 重定向响应;当代理关闭(或直接连接)时,App 也收到一个相同的 302 响应(响应头、状态码、Location 我都对比过,完全一致)。
核心问题:
当使用我自己的 Netty 代理时,该 App 在索尼登录流程后登录失败**(无法获取到最终的鉴权数据)。
当关闭 Netty 代理(直连)时,登录成功。
当在模拟器内部使用 HttpCanary(作为本地代理) 时,App 登录也成功(且我能看到目标请求和Cookie)。
矛盾点: 如果 Netty 代理和最终的无代理/HttpCanary 环境都收到了完全相同的 302 响应(我认为是登录成功的关键一步),为什么只有在使用我的 Netty 代理时 App 才登录失败? 它似乎对代理存在额外的、隐藏的依赖或限制。
补充细节:netty服务器有时候会打印/badrequest日志,是netty无法解析导致的,用httpcanary抓包登录流程则不会,我不确定是不是这个问题,我没有找到产生/badrequest的原因。
netty服务器重定向的302如下:
```java
HTTP/1.1 302 Moved Temporarily
Server: nginx
Content-Length: 0
X-Psn-Request-Id: 5b7bbc757e54bcc59c3e309f97f36962
X-Psn-Correlation-Id: b5a6eb55-c518-4879-accf-d74de2bdcd94
X-RequestId: 5b7bbc757e54bcc59c3e309f97f36962
X-CorrelationId: b5a6eb55-c518-4879-accf-d74de2bdcd94
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Expires: 0
Location: com.mlb.psn.app://redirect/?code=v3.t9Mczq&cid=b5a6eb55-c518-4879-accf-d74de2bdcd94
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Date: Fri, 06 Jun 2025 18:53:49 GMT
Connection: keep-alive
Set-Cookie: bm_sz=B7501ED00BA0FFCAC7BFDB859CB309CD~YAAQqffVF5p/1iiXAQAA6ZiXRhyrCEz5YqXI7fAemlL2vA5sPORdRCCLcGKZpfz0fQzQhNuU1Iy+mZ387kFBzlvIgLUA6qwqBbByc88z4DLCjftrCBqDKVZCauF8NLSVRjNSfdwE4glcFjGXxl1sK44/+iLYV/z/iWFnad2af6Qhwv47YJGZSXHBNdVXOznIhOcJiecHg5WXVSxIuQrquT+9Hub1OXEBeOjOmCo3KiWevPR2LnOyL+tDLfB6W6Cjy5RByD2qtK3Y3Dm6O3UvCuJHzCfJhWv3UvKush6KaciGx6qICmo1Y3rAMcvZGspurRkVj70jarvrEAVgsKAwt1fP8dHFMyHibeL8r+6decSGJ1G2fSpoQwp20yQMtHXkRmAeGhRoncnhywF+eIz+VnUNXqJpOjk4vfkKmG1ldG0m1SizhXV++FMtcHnwcUIqHcmg8iusdisZsiA0bkKrERXCmPlxQU+xQFDw6Gx7OZan/GLpFaTqNMy/0MZY5iCF2Eel+RcsCEE5UhrlOL0T57QNHsX4OzqhdaQOTP9SOYe637v8F5rzlFauei0NVirdQhnd9UdwPhBtvVWEOZQ=~3290936~3687985; Domain=.sony.com; Path=/; Expires=Fri, 06 Jun 2025 19:20:14 GMT; Max-Age=1585
httpcanary的重定向抓包如下:
HTTP/1.1 302 Moved Temporarily
Server: nginx
Content-Length: 0
X-Psn-Request-Id: 972740184ce63b0cabef69d79198dcac
X-Psn-Correlation-Id: 1f9f236c-31ea-40d1-b43a-6fffc2866cca
X-RequestId: 972740184ce63b0cabef69d79198dcac
X-CorrelationId: 1f9f236c-31ea-40d1-b43a-6fffc2866cca
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Expires: 0
Location: com.mlb.psn.app://redirect/?code=v3.6mJ92x&cid=1f9f236c-31ea-40d1-b43a-6fffc2866cca
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Date: Fri, 06 Jun 2025 19:06:40 GMT
Connection: keep-alive
Set-Cookie: bm_sz=A332E979CC0199FAC6C582D3109A7B18~YAAQj2rRF0f2lzyXAQAAVFyjRhyto6LKOPtRfPKVaAH4GWzGmzfyalEAqOhsd3bfX3LjrQouq0KUKR1DJTv89BwydT6Rp/AhllaCPa6yEg4xzpCsua9h7wZDALyQ66+kBD33NIw8Pj6oMOILzH+6QKm+H4KgMYjW0nhmIpv3KhccxEULBc9sXq/AFApivWp1RbiA6BnuhthCLzq0ZN8FF6zO7HxvwgjOb6AY0XjQMQ67Ca+a2fPiU6H+O+K8Oq31sdcFxVDaNlHgAC4S4Y+ntgmpjRsJe7QrFHfZbAjQgcD5gUScAfvS47+OgTmP0O+Q/0xmjdI/Me1azvAn7VE+eyxV2Qo50zbLQ6w8oFmTBULxn9kYK4ahUQZ16FUGOZSt8zkqCaWLsHsZ8oifgNRrVtXQKANUS2JuC/qa/G7qM129GJfqiTOWbeIfS8SGYt9m76TCWrvIRdk52YRBJySgSj5/tusL1n9SJHrGlf/USW9cMDlsCZa4m4QSAsKgjmqB4JHjAEP9Rd6C4MMIT8B5f8fG3Ru5xz87kI+Wq62tO4k0JfJ/KtNhMwLZxYwkGqheU0WM5rtD0TQvmjC1D1K0J2nT48lhD/uDbjvsFELEaUyO+5s=~3487043~3158597; Domain=.sony.com; Path=/; Expires=Fri, 06 Jun 2025 22:58:49 GMT; Max-Age=13929
```