1

你好吗?

我在 ExpressJS 中有一些 CSP 问题。如果我只使用头盔,它不会发生。但是,当我使用带头盔的 cors 包时,浏览器会抛出有关字体的错误。我不明白这个问题。

nodeJS 版本 14.16.1 express 版本 4.17.1 头盔版本 4.6.0 cors 版本 2.8.5

我不明白这个问题

我阅读了有关 cors 和 csp 的文档。所以,我用头盔写了关于 csp 的代码。

app.use(
  helmet.contentSecurityPolicy({
    useDefaults: true,
    directives: {
      "script-src": ["'unsafe-eval'"], //development mode should allow 'unsafe-eval' because eval function
      "img-src": ["'self'", "data:", "https:"],
      "frame-src": "https://www.youtube.com/",
      "font-src": ["'self'", "data:", "https:"],
      "style-src": [
        "'self'",
        "'unsafe-inline'",
        "https://cdnjs.cloudflare.com",
      ],
    },
  }),
);
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap");

@font-face {
  font-family: "Material Icons";
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.gstatic.com/s/materialicons/v107/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2)
    format("woff2");
}

它没有问题。但是,问题是当我编写有关 cors 的代码时,浏览器会抛出如上图所示的错误。

const whitelist = ["http://localhost:4000", "https://fonts.googleapis.com", "https://fonts.googleapis.com"];

export const corsOptions = {
  origin: (origin, callback) => {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error());
    }
  },
};

app.use(cors(corsOptions));

我不明白这个问题。我找不到解决方案。

我该如何解决这个问题?

========== 完整代码 =======

import express from "express";
import morgan from "morgan";
import rootRouter from "./router/root.router";
import worshipRouter from "./router/worship.router";
import noticeRouter from "./router/notice.router";
import api from "./router/api.router";
import userRouter from "./router/user.router";
import session from "express-session";
import cookieParser from "cookie-parser";
import MongoStore from "connect-mongo";
import helmet from "helmet";
import { locals, preUrl, corsOptions, csrfProtection } from "./middleWare";
import documentsRouter from "./router/documents.router";
import blogRouter from "./router/blog.router";
import permissionsPolicy from "permissions-policy";
import cors from "cors";

const app = express();

app.use((req, res, next) => {
  if (req.get("X-Forwarded-Proto") == "https" || req.hostname == "localhost") {
    next();
  } else if (
    req.get("X-Forwarded-Proto") != "https" &&
    req.get("X-Forwarded-Port") != "443"
  ) {
    res.redirect(`https://${req.hostname}${req.url}`);
  }
});

app.use(helmet());
app.use(
  helmet.contentSecurityPolicy({
    useDefaults: true,
    directives: {
      "script-src": ["'unsafe-eval'", process.env.URL], //development mode should allow 'unsafe-eval' because eval function
      "img-src": ["'self'", "data:", "https:"],
      "frame-src": "https://www.youtube.com/",
      "font-src": ["'self'", "data:", "https:"],
      "style-src": [
        "'self'",
        "'unsafe-inline'",
        "https://cdnjs.cloudflare.com",
      ],
    },
  }),
);
app.use(
  helmet.hsts({
    maxAge: 31536000,
    preload: true,
  }),
);
app.use(helmet.xssFilter());
app.use(
  permissionsPolicy({
    features: {
      fullscreen: ["self", '"https://www.youtube.com"'],
      displayCapture: ["self"],
      autoplay: [],
      camera: [],
    },
  }),
);

const whitelist = ["http://localhost:4000"];

export const corsOptions = {
  origin: (origin, callback) => {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error());
    }
  },
};

app.use(cors(corsOptions));

app.use(morgan("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(
  session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    expires: 1000 * 60 * 60 * 24,
    httpOnly: true,
    secure: true,
    store: MongoStore.create({
      mongoUrl: process.env.MONGO_URL,
    }),
  }),
);

app.use(csrfProtection);
app.use(function (err, req, res, next) {
  if (err.code !== "EBADCSRFTOKEN") return next(err);
  res.status(403).json({ error: "session has expired or tampered with" });
});

app.set("views", process.cwd() + "/src/views");
app.set("view engine", "pug");

app.use("/static", express.static("client"));
app.use("/favicon", express.static("favicon"));
app.use("/uploads", express.static("uploads"));

app.use((req, res, next) => {
  req.sessionStore.all((error, sessions) => {
    next();
  });
});

app.use(locals);
app.use("/", rootRouter);
app.use("/notice", noticeRouter);
app.use("/documents", documentsRouter);
app.use("/blog", blogRouter);

app.use("/user", userRouter);

app.use("/api", api);

export default app;

4

0 回答 0