helmet, hpp
서버의 각종 취약점을 보완해주는 패키지들이며, 익스프레스 미들웨어로서 사용할 수 있습니다.
이 패키지들을 사용한다고 해서 모든 취약점을 방어해주는 것이 아니므로 서버를 운영할 때는 주기적으로 취약점을 점검해야 합니다.
$ npm i helmet hpp
개발 환경에서는 사용할 필요가 없으므로 배포 환경일 때만 적용하면 됩니다.
const express = require("express");
const cookieParser = require("cookie-parser");
const morgan = require("morgan");
const path = require("path");
const session = require("express-session");
const nunjucks = require("nunjucks");
const dotenv = require("dotenv");
const passport = require("passport");
const helmet = require("helmet");
const hpp = require("hpp");
dotenv.config();
const pageRouter = require("./routes/page");
const authRouter = require("./routes/auth");
const postRouter = require("./routes/post");
const userRouter = require("./routes/user");
const { sequelize } = require("./models");
const passportConfig = require("./passport");
const logger = require("./logger");
const app = express();
passportConfig(); // 패스포트 설정
app.set("port", process.env.PORT || 8001);
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
watch: true,
});
sequelize
.sync({ force: false })
.then(() => {
console.log("데이터베이스 연결 성공");
})
.catch((err) => {
console.error(err);
});
if (process.env.NODE_ENV === "production") {
app.use(morgan("combined"));
app.use(helmet({ contentSecurityPolicy: false }));
app.use(hpp());
} else {
app.use(morgan("dev"));
}
app.use(express.static(path.join(__dirname, "public")));
app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use("/img", express.static(path.join(__dirname, "uploads")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
const sessionOption = {
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
};
if (process.env.NODE_ENV === "production") {
sessionOption.proxy = true;
}
app.use(session(sessionOption));
app.use(passport.initialize());
app.use(passport.session());
app.use("/", pageRouter);
app.use("/auth", authRouter);
app.use("/post", postRouter);
app.use("/user", userRouter);
app.use((req, res, next) => {
const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
error.status = 404;
logger.info("hello");
logger.error(error.message);
next(error);
});
app.use((err, req, res, next) => {
console.error(err);
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== "production" ? err : {};
res.status(err.status || 500);
res.render("error");
});
module.exports = app;
helmet가 hpp가 방어해주는 취약점 목록은 각각의 공식 문서에 나와 있습니다. 기본적으로는 배포 전에 이 두 패키지를 넣어주는 것이 좋습니다. 다만, 때때로는 너무 보안 규칙을 엄격하게 적용해서 방해되는 경우도 있으니 공식 문서를 보면서 필요 없는 옵션은 해제해야 합니다.