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.
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.
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: