头盔导致 Heroku 上托管的 MERN 应用程序导致错误:拒绝执行内联脚本,因为它违反了以下内容

Posted

技术标签:

【中文标题】头盔导致 Heroku 上托管的 MERN 应用程序导致错误:拒绝执行内联脚本,因为它违反了以下内容【英文标题】:Helmet causing MERN app hosted on heroku cause ERROR: Refused to execute inline script because it violates the following 【发布时间】:2021-04-29 14:29:09 【问题描述】:

我在 Heroku 上托管了我的 MERN 应用程序,但是每当我在 app.js 文件中实现头盔时,都会导致此问题。

const path = require('path');
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
// const cors = require('cors');
const rateLimit = require('express-rate-limit');
const helmet = require('helmet');
const mongoSanitize = require('express-mongo-sanitize');
const expressSanitizer = require('express-sanitizer');
const xss = require('xss-clean');
const hpp = require('hpp');
const compression = require('compression')

const authRouter = require('./routes/authRoutes');

const app = express();
// IMPLEMENT CORS
// app.use(cors());
// app.options('*', cors());
app.use((req, res, next) => 
   res.header('Access-Control-Allow-Origin', '*');
   res.header(
      'Access-Control-Allow-Headers',
      'Origin, X-Requested-With, Content-Type, Accept, Authorization'
   );
   if (req.method === 'OPTIONS') 
      res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, PATCH, DELETE');
      return res.status(200).json();
   
   return next();
);

//SECURITY
// app.use(helmet());  <------causing issue.

const limiter = rateLimit(
   max: 100,
   windowMs: 60 * 60 * 1000,// 1 hour
   message: 'Too many requests from this IP, please try again in an hour!'
)
app.use('/api', limiter);

// Body parser, reading data from body into req.body
app.use(express.json( limit: '10kb' ));
app.use(express.urlencoded( extended: true, limit: '10kb' ));
app.use(cookieParser());
// Data sanitization against NoSQL query injection
app.use(mongoSanitize());
// html sanitizer
app.use(expressSanitizer());
// Data sanitization against XSS
app.use(xss());
// Prevent parameter pollution
app.use(hpp(
   whitelist: ['tags', 'likeCounts', 'commentCounts']
));
// COMPRESSION
app.use(compression())
// logging 
if (process.env.NODE_ENV === 'development') 
   app.use(morgan('dev'));

应用程序在本地环境中运行良好,但头盔导致错误:

拒绝执行内联脚本,因为它违反了以下内容 内容安全策略指令:“script-src 'self'”。无论是 'unsafe-inline' 关键字,一个哈希 ('sha256-c8oXMAC5SpSNhKqLeKnZuBIrD93BdSvpZ47lOJrkmFE='),或随机数 ('nonce-...') 是启用内联执行所必需的。

我也尝试按照以下方法修复它:

    在项目根目录中创建一个 .env 文件 添加变量如下:INLINE_RUNTIME_CHUNK=false 再次构建项目并再次加载扩展。

但这无济于事。请指导我如何修复它以及在我的应用中实施其他安全措施的最佳方法是什么?

【问题讨论】:

【参考方案1】:

这里是头盔维护者。

发生这种情况是因为 Helmet 默认设置的内容安全策略。要解决您的问题,您需要配置 Helmet 的 CSP。

MDN has a good documentation about CSP 我建议您阅读它作为背景。之后,看看Helmet's README,看看如何配置它的CSP组件。

针对此问题提供一些帮助:此错误告诉您 CSP 的 script-src 指令不允许内联 javascript,因此被阻止。

这被认为是“内联”JavaScript:

<script>console.log('hello world!')</script>

然而,这不是:

<script src="/foo.js"></script>

有几种方法可以解决这个问题:

    将哈希或随机数添加到内联 &lt;script&gt; 并在您的 CSP 中使用。请参阅this example on MDN 寻求帮助。

    重构您的应用程序以完全避免内联脚本。

    更新您的 CSP 以允许不安全的内联脚本。你会做这样的事情:

    app.use(
      helmet(
        contentSecurityPolicy: 
          directives: 
            ...helmet.contentSecurityPolicy.getDefaultDirectives(),
            "script-src": ["'self'", "'unsafe-inline'", "example.com"],
          ,
        ,
      )
    );
    

    请注意,这被认为是不安全的。

    禁用 CSP。这是最危险的选择,所以我不推荐它。

    app.use(
      helmet(
        contentSecurityPolicy: false,
      )
    );
    

总而言之:要解决您的问题,您需要告诉 Helmet 配置您的 CSP。

【讨论】:

感谢您的快速回复。我最终得到了这段代码 -> app.use(helmet( contentSecurityPolicy: directives: defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", "https://codersleague.herokuapp.com"], styleSrc: ["'self'", 'https://fonts.googleapis.com', "'unsafe-inline'"], imgSrc: ["'self'", 'https://*.com'], fontSrc: ["'self'", 'https://*.com', 'data:'] , )); 因为我使用谷歌字体和 cloudinary 进行图像托管,所以我相应地对其进行了配置。

以上是关于头盔导致 Heroku 上托管的 MERN 应用程序导致错误:拒绝执行内联脚本,因为它违反了以下内容的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Heroku 上托管的 Ruby/Sinatra 应用程序中设置 HTTP 标头?

如何将客户端的正确 IP 地址获取到 Heroku 上托管的 Node socket.io 应用程序中?

如何将数据从 Heroku 上托管的 Node.js 应用程序发送到托管在完全独立(Cpanel)服务器上的 PHP 文件?

如何在 Heroku.com 上托管的 Redmine 上安装插件

如何解决 Heroku 上托管的 django 项目中的迁移问题?

我需要为 Heroku 上托管的机器人实现分片吗?