ForbiddenError: invalid csrf token nodejs and Angular Ionic app

ForbiddenError: invalid csrf token nodejs and Angular Ionic app

我正在使用 Ionic + Angular + NodeJs 应用程序来启用 CSRF 保护。有一段时间它工作正常,但突然停止工作并向我发送消息

ForbiddenError: invalid csrf token

我的代码很简单,几天以来我一直在努力寻找解决方法,但似乎所有尝试都失败了。

Node JS 服务器 运行 在端口 8089 上(例如)具有 CSRF 保护

// [This is only for test purpose]
app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Methods", "*");
    res.header("Access-Control-Allow-Headers", "X-XSRF-TOKEN, Origin, X-Requested-With, Content-Type, Accept, Authorization");
    next();
  });

  app.use(bodyParser.json({limit: '20mb'})); /* {limit: "20mb"} */
  app.use(cookieParser());
  const csrfProtection = csurf({
    cookie: true,
    ignoreMethods: ['GET', 'HEAD', 'OPTIONS'],
  });

// base url is /api --> e.g (localhost:8089/api)
// it didn't worked with / only
      app.use(config.base_url, csrfProtection, (req, res, next): void => {
        res.cookie('XSRF_TOKEN', req.csrfToken(), { httpOnly: false });
        next();
      });
      // csrfProtection is not yet applied
      app.use(config.base_url, csrfProtection, HelperRouter); //post route

Ionic 中的应用程序模块 + Angular

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    MenuComponentModule,
    FontAwesomeIconsModule,
    HttpClientModule,
    HttpClientXsrfModule.withOptions({
      cookieName: 'XSRF-TOKEN',
      headerName: 'X-XSRF-TOKEN',
    }),
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    { provide: HTTP_INTERCEPTORS, useClass: CSRFTokenInterceptor, multi: true }
  ],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}

我也试过添加 HttpInterceptor // 这也没用

@Injectable({
    providedIn: 'root'
})
export class CSRFTokenInterceptor implements HttpInterceptor {

  constructor(private tokenExtractor: HttpXsrfTokenExtractor) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const headerName = 'X-XSRF-TOKEN';
    const token = this.tokenExtractor.getToken() as string;
    console.log(token);
    if (token !== null && !req.headers.has(headerName)) {
      req = req.clone({ headers: req.headers.set(headerName, token) });
    }
    return next.handle(req);
  }
}

还在 Ionic + Angular 应用程序中启用了代理

{
    "/v0": {
      "target": "http://localhost:8089/api/",
      "secure": false,
      "logLevel" : "debug",
      "changeOrigin": true
    }
}

回应header

HTTP/1.1 403 Forbidden
x-powered-by: Express
access-control-allow-origin: *
server: nginx/1.19.0
date: Tue, 05 Jan 2021 11:38:10 GMT
content-type: text/html; charset=utf-8
content-length: 1018
connection: close
access-control-allow-methods: *
access-control-allow-headers: X-XSRF-TOKEN, Origin, X-Requested-With, Content-Type, Accept, Authorization
content-security-policy: default-src 'none'
x-content-type-options: nosniff

请求header

POST /v0/validateReferences HTTP/1.1
Host: localhost:4200
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: application/json, text/plain, */*
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 53
Origin: http://localhost:4200
Connection: keep-alive
Referer: http://localhost:4200/account/login
Cookie: _csrf=k5nvA7BbJQ9a2GvPdlpisfCQ

这是怎么回事

  1. 如果我禁用 CSRF 保护,该路由将起作用。
  2. 请求转到正确的路径。 /v0(来自代理)
  3. 前缀显示 CSRF 令牌。

我已将项目上传到 GitHub 以防有人试一试 Project link

CSRF实现终于解决了。完成的实现在 GitHub 项目中。 GitHub

一些改变帮助我完成了这些事情 首先我更改了 csrf get route root path

app.use('/', csrfProtection, (req, res, next): void => {
        res.cookie('XSRF_TOKEN', req.csrfToken(), { httpOnly: false });
        next();
});

然后我在 ionic angular app

中更改了代理配置文件
{
    "/api/v0/*": {
      "target": "http://localhost:8089/",
      "secure": false,
      "logLevel" : "debug",
      "changeOrigin": true
    } }

然后我改变了我的服务来调用端点

/api/v0/validate // post route

我已经在 GitHub 项目中添加了所有内容,所以如果有人遇到 CSRF 问题,他们可以使用该项目。