如何修改Helmet的CSP默认协议为HTTP以适配开发环境?
问题:开发环境中Helmet CSP强制HTTPS导致资源加载失败
初次使用Helmet为Node.js应用添加安全层,开发服务器采用HTTP协议,但配置的Content Security Policy(CSP)要求从HTTPS加载资源,导致必要的JavaScript和CSS文件无法正常加载。希望在开发环境中将CSP的资源加载协议改为HTTP,尝试设置maxAge为0无效,不想完全移除CSP。
当前Helmet配置代码:
const scriptSrcUrls = [ "https://polyfill.io", "https://maps.googleapis.com", "https://kit.fontawesome.com", "https://cdn.jsdelivr.net", ]; const styleSrcUrls = [ "https://kit-free.fontawesome.com", "https://cdn.jsdelivr.net", "https://maps.googleapis.com", "https://fonts.googleapis.com", "https://use.fontawesome.com", "https://polyfill.io" ]; const connectSrcUrls = [ "https://polyfill.io", "https://maps.googleapis.com", ]; const fontSrcUrls = [ "https://fonts.gstatic.com" ]; app.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: [], connectSrc: ["'self'", ...connectSrcUrls], scriptSrc: ["'unsafe-inline'", "'unsafe-eval'", "'self'", ...scriptSrcUrls], styleSrc: ["'self'", "'unsafe-inline'", ...styleSrcUrls], workerSrc: ["'self'", "blob:"], childSrc: ["blob:"], objectSrc: [], imgSrc: [ "'self'", "blob:", "data:", "https://maps.gstatic.com", "https://maps.googleapis.com", "https://images.unsplash.com", ], fontSrc: ["'self'", ...fontSrcUrls], }, }) );
解决方案
Helmet的CSP本身没有“默认协议”配置项,问题出在你硬编码了所有第三方资源的https://协议,导致开发环境HTTP页面加载资源时触发浏览器混合内容限制。以下是两种可行的解决方法:
方法1:使用协议相对URL(推荐)
将所有https://开头的资源地址改为//,浏览器会自动适配当前页面的协议(开发环境用HTTP,生产环境用HTTPS)加载资源:
// 改用协议相对URL const scriptSrcUrls = [ "//polyfill.io", "//maps.googleapis.com", "//kit.fontawesome.com", "//cdn.jsdelivr.net", ]; const styleSrcUrls = [ "//kit-free.fontawesome.com", "//cdn.jsdelivr.net", "//maps.googleapis.com", "//fonts.googleapis.com", "//use.fontawesome.com", "//polyfill.io" ]; const connectSrcUrls = [ "//polyfill.io", "//maps.googleapis.com", ]; const fontSrcUrls = [ "//fonts.gstatic.com" ]; const imgSrcUrls = [ "//maps.gstatic.com", "//maps.googleapis.com", "//images.unsplash.com", ]; app.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: [], connectSrc: ["'self'", ...connectSrcUrls], scriptSrc: ["'unsafe-inline'", "'unsafe-eval'", "'self'", ...scriptSrcUrls], styleSrc: ["'self'", "'unsafe-inline'", ...styleSrcUrls], workerSrc: ["'self'", "blob:"], childSrc: ["blob:"], objectSrc: [], imgSrc: [ "'self'", "blob:", "data:", ...imgSrcUrls ], fontSrc: ["'self'", ...fontSrcUrls], }, }) );
方法2:根据环境动态配置
通过环境变量判断当前运行环境,在开发环境下允许HTTP资源加载:
const isDevelopment = process.env.NODE_ENV === 'development'; // 基础源配置 const scriptSrcUrls = [ "https://polyfill.io", "https://maps.googleapis.com", "https://kit.fontawesome.com", "https://cdn.jsdelivr.net", ]; const styleSrcUrls = [ "https://kit-free.fontawesome.com", "https://cdn.jsdelivr.net", "https://maps.googleapis.com", "https://fonts.googleapis.com", "https://use.fontawesome.com", "https://polyfill.io" ]; const connectSrcUrls = [ "https://polyfill.io", "https://maps.googleapis.com", ]; const fontSrcUrls = [ "https://fonts.gstatic.com" ]; // 开发环境添加HTTP协议允许规则 const devHttpAllowance = isDevelopment ? ["http:"] : []; app.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: [], connectSrc: ["'self'", ...connectSrcUrls, ...devHttpAllowance], scriptSrc: ["'unsafe-inline'", "'unsafe-eval'", "'self'", ...scriptSrcUrls, ...devHttpAllowance], styleSrc: ["'self'", "'unsafe-inline'", ...styleSrcUrls, ...devHttpAllowance], workerSrc: ["'self'", "blob:"], childSrc: ["blob:"], objectSrc: [], imgSrc: [ "'self'", "blob:", "data:", "https://maps.gstatic.com", "https://maps.googleapis.com", "https://images.unsplash.com", ...devHttpAllowance ], fontSrc: ["'self'", ...fontSrcUrls, ...devHttpAllowance], }, }) );
注意:maxAge控制的是CSP规则的缓存时间,和协议限制无关,因此设置为0无法解决你的问题。
内容的提问来源于stack exchange,提问作者bensmith87
相关产品推荐
相关产品推荐

