Ionic安卓端请求丢失Header,显示Provisional Headers are shown求助
我之前在做Ionic+Angular项目时也遇到过几乎一模一样的问题——浏览器里一切正常,但安卓设备上请求要么丢Header,要么弹出"Provisional Headers are shown"的提示,折腾了好久才找到几个可行的方案,分享给你:
先搞清楚问题根源
"Provisional Headers are shown"这个提示本质是请求没有真正发送到服务器,被安卓WebView的安全策略拦截了。结合你的代码和后端情况,主要有两个核心原因:
- 当
withCredentials: true时,后端返回的Access-Control-Allow-Origin: *是不合法的(浏览器可能宽松处理,但安卓WebView严格执行CORS规则) - 安卓WebView对跨域Cookie的处理和浏览器不一致,导致Cookie(也就是你依赖的
.DOTNETNUKE令牌)无法被保存和携带
下面是具体的解决方案,按优先级排序:
方案1:改用Ionic Native HTTP插件(最可靠)
这个方案直接绕过WebView的CORS限制,用原生系统的HTTP请求发送数据,能完美解决Header和Cookie的问题:
步骤1:安装插件
# 安装cordova原生插件 ionic cordova plugin add cordova-plugin-advanced-http # 安装Ionic Native封装 npm install @ionic-native/http
步骤2:在AppModule中注册
import { HTTP } from '@ionic-native/http/ngx'; @NgModule({ declarations: [AppComponent], imports: [...], providers: [ ... HTTP, // 添加到providers { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } ], bootstrap: [AppComponent] }) export class AppModule {}
步骤3:重构你的HTTP服务
把原来基于Angular HttpClient的代码改成用Native HTTP:
import { HTTP } from '@ionic-native/http/ngx'; // ... constructor(private nativeHttp: HTTP) {} public get(pageName, action, params2): Promise<any> { const requestUrl = this.host + HTTP_CONFIG[pageName][action].URL; // 原生HTTP会自动处理Cookie存储和携带,不需要手动设置withCredentials return this.nativeHttp.get(requestUrl, params2, {}) .then(response => { // 原生返回的data是字符串,需要手动解析成JSON const parsedData = JSON.parse(response.data); console.log("Response: ", parsedData); return parsedData; }) .catch(error => { console.error("Request failed: ", error); throw error; }); }
这个方案的优势是完全避开WebView的限制,原生HTTP请求会自动管理Cookie,后续请求会自动带上.DOTNETNUKE令牌,认证功能就能正常工作了。
方案2:调整安卓WebView的配置(如果不想换插件)
如果坚持用Angular HttpClient,可以尝试修改WebView的安全策略,允许跨域Cookie和宽松的CORS规则:
步骤1:修改config.xml
在项目根目录的config.xml中添加这些配置:
<!-- 允许跨域导航 --> <allow-navigation href="*" /> <!-- 允许所有源的请求 --> <access origin="*" /> <!-- 启用DOM存储,用来保存Cookie --> <preference name="AndroidInsecureFileModeEnabled" value="true" /> <preference name="DomStorageEnabled" value="true" />
步骤2:在AppComponent中配置WebView
import { Platform } from '@ionic/angular'; import { WebView } from '@ionic-native/ionic-webview/ngx'; constructor(private platform: Platform, private webView: WebView) { this.platform.ready().then(() => { if (this.platform.is('android')) { const engine = this.webView.getEngine(); if (engine instanceof android.webkit.WebView) { const settings = engine.getSettings(); // 启用DOM存储 settings.setDomStorageEnabled(true); // 允许跨域Cookie android.webkit.CookieManager.getInstance().setAcceptThirdPartyCookies(engine, true); // 放宽跨域资源访问限制 settings.setAllowUniversalAccessFromFileURLs(true); } } }); }
步骤3:修正withCredentials的逻辑
确保你的登录请求和后续所有需要携带Cookie的请求,withCredentials都设为true,而且不要依赖后端的Access-Control-Allow-Origin: *(如果后端不能改,这个方案可能有局限性,因为CORS规则要求带credentials时不能用通配符)。
额外提醒:关于GET传密码的风险
虽然和当前问题无关,但还是要提一句:用GET请求把密码放在URL参数里是非常不安全的,密码会被记录在服务器日志、浏览器历史甚至网络监控中。如果以后有机会修改后端,建议改成POST请求,把登录信息放在请求体里。
内容的提问来源于stack exchange,提问作者Joris Guyonnet

