Angular 17本地SSR+SSL环境下无法调用.NET Core后端求助
Angular 17.0.3迁移后Postman模拟爬虫请求API失败问题
问题背景
本地通过npm start运行Angular项目,启动命令配置如下:
"start": "ng serve --ssl --ssl-cert %APPDATA%\\ASP.NET\\https\\%npm_package_name%.pem --ssl-key %APPDATA%\\ASP.NET\\https\\%npm_package_name%.key --host=127.0.0.1"
网站在浏览器中可正常访问,但使用Postman模拟Facebook爬虫请求URL时,前端无法调用.NET Core后端接口,自定义Http拦截器输出错误:
ErrorHandlerService 0 - "Http failure response for https://localhost:7093/api/Product/LoadProduct/21275402: 0 undefined" Error at eval (c:/GitHub/iperedil/angularapp/src/app/error-handler.services.ts:25:37) at _Observable.init (c:/GitHub/iperedil/angularapp/node_modules/rxjs/dist/esm/internal/observable/throwError.js:5:51) at _Observable._trySubscribe (c:/GitHub/iperedil/angularapp/node_modules/rxjs/dist/esm/internal/Observable.js:37:25) at eval (c:/GitHub/iperedil/angularapp/node_modules/rxjs/dist/esm/internal/operators/catchError.js:14:31)
直接在浏览器中访问接口https://localhost:7093/api/Product/LoadProduct/21275402可正常返回数据,该问题为Angular 17.0.3迁移后出现。
注释拦截器部分代码后,获得更详细错误信息:
HttpErrorResponse { headers: _HttpHeaders { normalizedNames: Map(0) {}, lazyUpdate: null, headers: Map(0) {} }, status: 0, statusText: 'Unknown Error', url: 'https://localhost:7093/api/Product/LoadProduct/21275402', ok: false, name: 'HttpErrorResponse', message: 'Http failure response for https://localhost:7093/api/Product/LoadProduct/21275402: 0 undefined', error: TypeError: fetch failed at node:internal/deps/undici/undici:12345:11 at _ZoneDelegate.invoke (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:368:26) at Object.onInvoke (c:/GitHub/iperedil/angularapp/node_modules/@angular/core/fesm2022/core.mjs:14424:33) at _ZoneDelegate.invoke (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:367:52) at _Zone.run (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:130:43) at eval (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:1191:36) at _ZoneDelegate.invokeTask (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:403:31) ... 2 lines matching cause stack trace ... at _ZoneDelegate.invokeTask (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:402:36) { cause: Error: self-signed certificate at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34) at _ZoneDelegate.invokeTask (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:403:31) at eval (c:/GitHub/iperedil/angularapp/node_modules/@angular/core/fesm2022/core.mjs:14098:55) at AsyncStackTaggingZoneSpec.onInvokeTask (c:/GitHub/iperedil/angularapp/node_modules/@angular/core/fesm2022/core.mjs:14098:36) at _ZoneDelegate.invokeTask (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:402:36) at Object.onInvokeTask (c:/GitHub/iperedil/angularapp/node_modules/@angular/core/fesm2022/core.mjs:14411:33) at _ZoneDelegate.invokeTask (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:402:36) at _Zone.runTask (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:174:47) at invokeTask (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:484:34) at TLSSocket.ZoneTask.invoke (c:/GitHub/iperedil/angularapp/node_modules/zone.js/fesm2015/zone-node.js:473:48) { code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
自定义Http拦截器代码
export class ErrorHandlerService implements HttpInterceptor { constructor(private router: Router, private authservice: AuthService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(req) .pipe( catchError((error: HttpErrorResponse) => { console.log('ErrorHandlerService ' + error.status + ' - ' + JSON.stringify(error.message)); // HERE if (error instanceof HttpErrorResponse && error.status === 401 && } else { return throwError(() => new Error(errorMessage)); } }) ) }
问题分析与解决方案
核心原因
从错误信息中的DEPTH_ZERO_SELF_SIGNED_CERT可知,问题根源是自签名证书不被Node.js环境信任。Angular 17默认使用Node.js的fetch API发起请求,而fetch会严格验证证书合法性;浏览器允许用户手动信任自签名证书,但Postman模拟爬虫请求时,前端在Node环境下的请求会被拦截。
解决方案
1. 开发环境临时方案
禁用证书验证(仅本地开发)
启动项目时添加环境变量跳过证书校验:set NODE_TLS_REJECT_UNAUTHORIZED=0 && npm start注意:此方法仅适用于本地开发,生产环境禁止使用。
将自签名证书加入系统信任列表
将%APPDATA%\ASP.NET\https\%npm_package_name%.pem证书导入系统根证书目录,Node.js会继承系统信任配置,无需修改代码。
2. 长期推荐方案
使用mkcert工具生成本地可信证书:
- 安装mkcert工具
- 生成并安装本地CA:
mkcert -install - 为localhost生成证书:
mkcert localhost 127.0.0.1 - 修改Angular启动命令,使用新证书:
"start": "ng serve --ssl --ssl-cert ./localhost.pem --ssl-key ./localhost-key.pem --host=127.0.0.1"
3. 拦截器代码修复
原拦截器存在语法错误(if语句未闭合),修复后代码如下:
export class ErrorHandlerService implements HttpInterceptor { constructor(private router: Router, private authservice: AuthService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(req) .pipe( catchError((error: HttpErrorResponse) => { console.log('ErrorHandlerService ' + error.status + ' - ' + JSON.stringify(error.message)); let errorMessage = '未知错误'; if (error instanceof HttpErrorResponse) { if (error.status === 401) { // 处理401逻辑,例如跳转登录页 this.router.navigate(['/login']); errorMessage = '未授权访问'; } else { errorMessage = error.message || `错误状态码: ${error.status}`; } } return throwError(() => new Error(errorMessage)); }) ); } }
内容的提问来源于stack exchange,提问作者Lluthus
相关产品推荐
相关产品推荐

