将工作 Web 应用程序转变为适用于 Android 的本机 Ionic 应用程序时出现 CORS 问题
Posted
技术标签:
【中文标题】将工作 Web 应用程序转变为适用于 Android 的本机 Ionic 应用程序时出现 CORS 问题【英文标题】:CORS issue while shaping working web app into a native Ionic app for Android 【发布时间】:2020-12-23 20:04:06 【问题描述】:我一直试图在guide 之后设置这个 Ionic CLI 代理服务器,但它是从 2015 年开始的,我不知道如何在 Angular 10 中实现它。
所以当我使用命令运行我的应用程序时:
ionic capacitor run android --project=myApp -c=production
我在 Android Studio 中有这个错误:
E/Capacitor/Console: File: http://localhost/login - Line 0 - Msg: Access to XMLHttpRequest at 'https://remoteServer.com/api/v1/oauth/v2/token' from origin 'http://localhost' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' head
这是我的 capacitor.config.json 文件:
"appId": "io.ionic.starter",
"appName": "myApp",
"bundledWebRuntime": false,
"npmClient": "npm",
"webDir": "www",
"plugins":
"SplashScreen":
"launchShowDuration": 0
,
"cordova": ,
"linuxAndroidStudioPath": "/opt/android-studio/bin/studio.sh"
这是我的 ionic.config.json 文件:
"name": "myApp",
"integrations":
"capacitor":
,
"type": "angular",
"proxies": [
"path": "/api",
"proxyUrl": "https://remoteServer.com/api"
]
离子信息
Ionic:
Ionic CLI : 6.10.1 (/home/user/.nvm/versions/node/v12.18.3/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/angular 5.3.1
@angular-devkit/build-angular : 0.1000.5
@angular-devkit/schematics : 10.0.5
@angular/cli : 10.0.5
@ionic/angular-toolkit : 2.3.3
Capacitor:
Capacitor CLI : 2.4.0
@capacitor/core : 2.4.0
Utility:
cordova-res : not installed
native-run : not installed
System:
NodeJS : v12.18.3 (/home/user/.nvm/versions/node/v12.18.3/bin/node)
npm : 6.14.6
OS : Linux 5.4
任何想法如何解决这个问题?我一直在寻找年龄......
编辑:
所以我按照 Angular 在 how to make an interceptor 和这篇解释 how to implement both HttpClient and Ionic's native HTTP 的文章中的说明进行操作,但遇到了新问题。
使用文章中的代码,TS 抱怨这一行:
headers: nativeHttpResponse.headers
(property) headers?: HttpHeaders
Type ' [key: string]: string; ' is missing the following properties from type 'HttpHeaders': headers, normalizedNames, lazyInit, lazyUpdate, and 12 more.ts(2740)
http.d.ts(3406, 9): The expected type comes from property 'headers' which is declared here on type ' body?: any; headers?: HttpHeaders; status?: number; statusText?: string; url?: string; '
这是整个 native-http.interceptor.ts:
import Injectable from "@angular/core";
import
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent,
HttpResponse,
from "@angular/common/http";
import Observable, from from "rxjs";
import Platform from "@ionic/angular";
import HTTP from "@ionic-native/http/ngx";
type HttpMethod =
| "get"
| "post"
| "put"
| "patch"
| "head"
| "delete"
| "upload"
| "download";
@Injectable()
export class NativeHttpInterceptor implements HttpInterceptor
constructor(private nativeHttp: HTTP, private platform: Platform)
public intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>>
if (!this.platform.is("cordova"))
return next.handle(request);
return from(this.handleNativeRequest(request));
private async handleNativeRequest(
request: HttpRequest<any>
): Promise<HttpResponse<any>>
const headerKeys = request.headers.keys();
const headers = ;
headerKeys.forEach((key) =>
headers[key] = request.headers.get(key);
);
try
await this.platform.ready();
const method = <HttpMethod>request.method.toLowerCase();
// console.log(‘— Request url’);
// console.log(request.url)
// console.log(‘— Request body’);
// console.log(request.body);
const nativeHttpResponse = await this.nativeHttp.sendRequest(
request.url,
method: method,
data: request.body,
headers: headers,
serializer: "json",
);
let body;
try
body = JSON.parse(nativeHttpResponse.data);
catch (error)
body = response: nativeHttpResponse.data ;
const response = new HttpResponse(
body: body,
status: nativeHttpResponse.status,
headers: nativeHttpResponse.headers, <--------
url: nativeHttpResponse.url,
);
// console.log(‘— Response success’)
// console.log(response);
return Promise.resolve(response);
catch (error)
if (!error.status)
return Promise.reject(error);
const response = new HttpResponse(
body: JSON.parse(error.error),
status: error.status,
headers: error.headers,
url: error.url,
);
return Promise.reject(response);
这是我的app.module.ts
的样子:
import BrowserModule from '@angular/platform-browser';
import NgModule from '@angular/core';
import RouterModule from '@angular/router';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import BrowserAnimationsModule from '@angular/platform-browser/animations';
import IonicModule from '@ionic/angular';
import HTTP from '@ionic-native/http/ngx';
import CoreModule from './core/core.module';
import SharedModule from './shared/shared.module';
import AppComponent from './app.component';
import PageNotFoundComponent from './shared/page-not-found/page-not-found.component';
import appRoutes from './app.routes';
@NgModule(
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
SharedModule,
CoreModule,
RouterModule.forRoot(
appRoutes
),
IonicModule.forRoot()
],
providers: [HTTP],
declarations: [
AppComponent,
PageNotFoundComponent
],
bootstrap: [AppComponent]
)
export class AppModule
这是我的core.module.ts
(我想在其中使用拦截器)的样子:
import NgModule from "@angular/core";
import CommonModule from "@angular/common";
import HTTP_INTERCEPTORS, HttpClientModule from "@angular/common/http";
import NativeHttpInterceptor from "./service/native-http.interceptor";
import AuthService from "./service/auth.service";
import ApiService from "./service/api.service";
import AuthGuardService from "./service/auth-guard.service";
import AuthInterceptor from "./service/auth-interceptor";
import WindowRef from "./service/window-ref-service";
@NgModule(
imports: [CommonModule, HttpClientModule],
providers: [
provide: HTTP_INTERCEPTORS,
useClass: NativeHttpInterceptor,
multi: true,
,
AuthService,
ApiService,
AuthGuardService,
WindowRef,
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true,
,
],
)
export class CoreModule
【问题讨论】:
您是否有权访问服务器以应用一些配置? 这里是 CORS 的更新 Ionic 文章:ionicframework.com/docs/troubleshooting/cors @yazantahhan 不,我无权更改 BE 上的任何内容。感谢您提供链接。 你能把抱怨标题的代码块放上去吗? @yazantahhan 添加了 TS 错误 + native-http.interceptor.ts & app.module.ts & core.module.ts 【参考方案1】:代理配置仅适用于原生构建的 ionic serve
或 livereload
。
如果您无法更改 BE 中的任何选项,那么最简单的方法是对 HTTP 请求使用本机插件cordova-plugin-advanced-http,它将发送不带原始标头的请求(因为它不是从浏览器发送的)。
您可以使用来自 here 的 Ionic Native 包装器。
【讨论】:
您是否知道我能否以及如何相对轻松地用这个 HTTP 插件替换我的 HttpClient?我在 api.service 中有数百行代码需要修改... 你可以有一个拦截器来为你做这件事。创建一个HTTP interceptor,它将捕获所有请求和响应,然后您将使用插件而不是 HttpClient 来发送请求。它需要一些工作,但这是最好的方法,因此您不必更改所有其他地方。您的所有逻辑都将集中在一个地方 你可以查看这个:manuel-heidrich.dev/blog/… 是否有一个具有此实现的示例项目?我不能让它工作...... TS 在这一行抱怨“headers”类型: headers: nativeHttpResponse.headers以上是关于将工作 Web 应用程序转变为适用于 Android 的本机 Ionic 应用程序时出现 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章
使用本地系统应用程序池标识时,进程仅适用于 Web 应用程序
适用于 Windows 8 应用商店 Web 资源的 Worklight 加密