it-swarm.com.de

Knoten js csrf Token-Schutz funktioniert nicht

Ich habe auf meiner app.js-Dateiserver-Seite nach bodyParser Folgendes:

let dotEnv = require("dotenv");
dotEnv.load();
let express = require("express");
let app = express();
if (process.env.NODE_ENV === 'production') {
  app = require('./public/web/server').app;
}
let passport = require("passport");
let server = require("http").Server(app);
let io = require("socket.io").listen(server);
// load intial configuration
require("./startup/initial-configuration")(app, io);
require("./server/config/socket")(io);
require("./server/config/database")(app, process.env.NODE_ENV);
require("./server/authentication/passport.local")(passport);
require("./server/authentication/passport.impersonate");
require("./startup/initial-routes")(app);
if (process.env.NODE_ENV === 'production') {
  app.get('*.*', express.static('./public/web/browser', {
  maxAge: '1y'
}));
app.get('*', (req, res) => {
  res.render('index', {
   req,
   res
  }, (err, html) => {
    if (html) {
      res.send(html);
    } else {
      // console.error(err);
      res.send(err);
    }
   });
  });
 }
 require("./server/middleware/custom-middleware")(app);
 module.exports = { app: app, server: server };

Wie Sie sehen, habe ich eine Datei initial-configuration in app.js geladen. Der Inhalt dieser Datei ist:

const path = require("path");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
const csurf = require("csurf");
const helmet = require("helmet");
const compression = require("compression");
const useragent = require("express-useragent");
const cors = require("cors");
const passport = require("passport");
const express = require("express");
const cookieMiddleware = require("../server/middleware/cookie-middleware");
const checkCSRFMiddleware = require("../server/middleware/checkCSRF-middleware");
const notificationModel = require("../server/model/notification/notification.model");
const logger = require("./logger");
const morgan = require("morgan");
module.exports = (app, io) => {
 app.set("case sensetive routing", true);
 if (process.env.NODE_ENV === "production") {
   app.enable("trust proxy");
 }
 app.use((req, res, next) => {
   res.io = io;
   res.header(
    "Access-Control-Allow-Headers",
    "X-CSRF-Token, Content-Type"
   );
  notificationModel.setIO(io);
  next();
 });

 let corsOption = {
   Origin: true,
   methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
   credentials: true,
   exposedHeaders: ["x-auth-token"]
 };

 app.use(cors(corsOption));
 // app.use(logger('dev'));
 app.use(helmet());
 app.use(useragent.express());
 app.use(compression());
 app.use(bodyParser.json());
 app.use(
   bodyParser.urlencoded({
    extended: false
  })
 );
 app.use(cookieParser());
 app.use(cookieMiddleware);
 app.use(passport.initialize());
 app.use(require('csurf')({cookie: true}))
 // error handler
 app.use(function (err, req, res, next) {
  if (err.code !== 'EBADCSRFTOKEN') return next(err)
  // handle CSRF token errors here
  res.status(403)
  res.send('session has expired or form tampered with')
 })
 app.use(function (req, res, next) {
 res.cookie('XSRF-TOKEN', req.csrfToken())
 next()
})

// app.use(express.static(path.join(__dirname, "../public/web/browser")));
app.use(
 morgan("combined", {
   stream: logger.stream
 })
);
};

Und in Angular habe ich nur folgende Zeilen in app.module importiert

HttpClientXsrfModule.withOptions({
  cookieName: "XSRF-TOKEN",
  headerName: "X-CSRF-TOKEN"
}),

Und alle meine Anforderungsheader haben Cookie:_csrf=TmghRq3eWC-PxQfp6pvuHw07; XSRF-TOKEN=vMPrZZtA--BgtY1YVqDRXmi5A6RSbMNb61JA

Aber alle meine Postanfragen sind fehlgeschlagen und sagen code: "EBADCSRFTOKEN".

Sollte ich etwas an der eckigen Seite machen? Soll ich das mit Formulardaten anhängen?

Für jede Hilfe danke. 

Hier sind meine Anfragedetails  request details

 my login request

7
jones

In Ihrem Code verwenden Sie viele Module. Um das Problem einzugrenzen, schlage ich vor, den Code auf eine Minimalversion zu reduzieren, indem alles entfernt wird, was nicht zwingend erforderlich ist, um csrf zu aktivieren.

Dies ist nur ein Vorschlag. In meiner Anwendung von Angular 7 habe ich Folgendes hinzugefügt (Cookiename und Token müssen nicht geändert werden, da sie im Angular-Quellcode Standardwerte enthalten):

HttpClientModule,
HttpClientXsrfModule.withOptions()

in meinem Server (Hauptdatei app.js) mit Express 4 habe ich dann diesen Code (in genau dieser Reihenfolge) hinzugefügt:

const csrf = require('csurf');
app.use(bodyParser.urlencoded({
  extended: false
}));
// then add cookie parser and csrf config
app.use(cookieParser());
app.use(csrf({
  cookie: {
    // here you can configure your cookie. Default values are ok, but I decided to be more explicit
    // http://expressjs.com/en/4x/api.html#req.cookies
    key: '_csrf',
    path: '/',
    httpOnly: false, // if you want you can use true here
    secure: false, // if you are using HTTPS I suggest true here
    signed: false, // I don't know if csurf supports signed cookies, so I used false
    // not mandatory, but if you want you can use sameSite: 'strict'
    // sameSite: 'strict', // https://www.owaspsafar.org/index.php/SameSite
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
   }
}));
app.use((req, res, next) => {
  const csrfTokenToSendToFrontEnd = req.csrfToken();
  console.log('csrfTokenToSendToFrontEnd: ', csrfTokenToSendToFrontEnd);
  // this cookie must be XSRF-TOKEN, because already defined as default in Angular.
  res.cookie('XSRF-TOKEN', csrfTokenToSendToFrontEnd);
  next();
});

// here requires the api file with all your rest apis (not static paths)
const routesApi = require('./src/routes/index')(express, passport);
app.use('/api', routesApi);

Und vor dem Ende der Datei (vor der 500-Middleware) habe ich Folgendes hinzugefügt, um Fehler zu behandeln:

// error handler
app.use((err, req, res, next) => {
  if (err.code !== 'EBADCSRFTOKEN') {
    return next(err);
  }
  res.status(403).json({
    message: 'error'
  });
});

Ich habe nur relevanten Code kopiert. Wenn Sie Fragen haben, wenden Sie sich bitte an meinen Code, wenn ich etwas vergessen habe.

3
Stefano Cappa

Es gibt mehrere Module, mit deren Hilfe Sie CSRF-Token in Ihrer Anwendung implementieren können. Einer von ihnen ist Csurf. Installieren Sie dieses Modul zusammen mit den Cookie-Parser-Abhängigkeiten, indem Sie Folgendes ausführen:

npm install cookie-parser csurf --save

Bei beiden Modulen handelt es sich um Middleware, die das Verhalten einer Anforderung in Express ändern kann. Wir verwenden bereits Body-Parser, um unseren POST -Körper zu analysieren, um die Nachricht abzurufen. Zusätzlich verwenden wir es, um nach dem _csrf-Token zu suchen. Die Cookie-Parser-Middleware überprüft, ob das Token in den Cookies vorhanden ist, und csurf ist der automatische Schutz für alle POST-, PUT-, PATCH- oder DELETE-Vorgänge, indem überprüft wird, ob das _csrf-Token sowohl in den Cookies als auch im Request-Body vorhanden ist Sie passen.

Fügen Sie der Datei index.js den folgenden Code hinzu, um die Middleware zu konfigurieren:

const express = require('express');
const bodyParser = require('body-parser');
const csurf = require('csurf');
const cookieParser = require('cookie-parser');

const PORT = process.env.PORT || 3000;
const app = express();

const csrfMiddleware = csurf({
  cookie: true
});

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(cookieParser());
app.use(csrfMiddleware);

app.get('/', (req, res) => {
  res.send(`
    <h1>Hello World</h1>
    <form action="/entry" method="POST">
      <div>
        <label for="message">Enter a message</label>
        <input id="message" name="message" type="text" />
      </div>
      <input type="submit" value="Submit" />
      <input type="hidden" name="_csrf" value="${req.csrfToken()}" />
    </form>
  `);
});

app.post('/entry', (req, res) => {
  console.log(`Message received: ${req.body.message}`);
  res.send(`CSRF token used: ${req.body._csrf}, Message received: ${req.body.message}`);
});

app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}`);
});

Starten Sie Ihren Server neu und navigieren Sie zu http: // localhost: 3000 . Geben Sie einen Text in das Eingabefeld ein und klicken Sie auf Senden. Sie sollten sehen, dass die Nachricht in der Konsole angezeigt wird und im Browser mit einer Nachricht wie der folgenden Nachricht begrüßt wird:

0
Rubin bhandari