You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Spring Boot服务的Angular SPA添加CSP nonce以允许内联JS/样式

Spring Boot + Angular SPA 配置CSP Nonce 解决Google Maps内联样式报错方案

核心实现逻辑

每次客户端请求页面时,后端生成唯一安全随机nonce,注入到CSP响应头和返回的Angular入口index.html中,前端将nonce同步给Angular框架和第三方资源,满足CSP校验要求。


步骤1:Spring Boot 后端配置Nonce生成与注入

1.1 新增CSP Nonce全局过滤器

每次请求生成随机nonce,同时将nonce写入CSP响应头:

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.crypto.codec.Hex;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.SecureRandom;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CspNonceFilter implements Filter {
    // 使用安全随机数生成器,禁止用Random等弱随机实现
    private final SecureRandom secureRandom = new SecureRandom();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        // 生成128位nonce,转16进制字符串
        byte[] nonceBytes = new byte[16];
        secureRandom.nextBytes(nonceBytes);
        String nonce = new String(Hex.encode(nonceBytes));
        req.setAttribute("cspNonce", nonce);

        // 拼接完整CSP头,把nonce加入script-src和style-src指令
        String csp = String.format("""
            img-src 'self' data: maps.gstatic.com *.googleapis.com *.ggpht.com https://www.google-analytics.com;
            connect-src 'self' https://www.google-analytics.com *.a2develop.com;
            script-src 'self' maps.googleapis.com www.googletagmanager.com 'nonce-%s';
            style-src 'self' maps.googleapis.com https://www.google-analytics.com https://ssl.google-analytics.com 'nonce-%s'
            """, nonce, nonce);
        resp.setHeader("Content-Security-Policy", csp);

        chain.doFilter(request, response);
    }
}

1.2 配置SPA入口页渲染

将Angular的index.html从static目录移动到templates目录,引入轻量模板引擎(比如Thymeleaf),新增控制器处理SPA路由,把nonce注入到index.html的占位符中:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import jakarta.servlet.http.HttpServletRequest;

@Controller
public class SpaIndexController {
    // 匹配所有SPA前端路由,排除静态资源路径
    @GetMapping(value = {"/", "/**/{path:[^\\.]*}"})
    public String renderIndex(HttpServletRequest request, Model model) {
        String nonce = (String) request.getAttribute("cspNonce");
        model.addAttribute("cspNonce", nonce);
        return "index";
    }
}

步骤2:Angular 前端适配Nonce

2.1 入口页新增nonce占位符

在index.html的head中新增meta标签存储nonce,同时给所有自定义内联脚本/样式标签加上nonce属性:

<head>
  <!-- 存储nonce供Angular读取 -->
  <meta name="csp-nonce" th:content="${cspNonce}">
  <!-- 示例:内联脚本加nonce属性 -->
  <script th:nonce="${cspNonce}">
    // 自定义内联脚本逻辑
  </script>
</head>

注:上述th:前缀是Thymeleaf语法,如果你用其他模板引擎,替换成对应占位符语法即可。

2.2 Angular框架注入Nonce

在app.module.ts中配置Angular官方提供的CSP_NONCE注入令牌,让Angular生成的内联样式自动带上nonce:

import { NgModule, CSP_NONCE } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

// 从meta标签读取后端注入的nonce
export function getCspNonce(): string {
  const nonceMeta = document.querySelector<HTMLMetaElement>('meta[name="csp-nonce"]');
  return nonceMeta?.content || '';
}

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [
    {
      provide: CSP_NONCE,
      useFactory: getCspNonce
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

临时替代方案(无需改代码)

如果暂时不想部署nonce全链路配置,可以直接把报错中给出的哈希值加入CSP的style-src指令:

style-src 'self' maps.googleapis.com https://www.google-analytics.com https://ssl.google-analytics.com 'sha256-a2VR/Wq1VPr0+3GRY+lEmAQm7wjwwnDtPpcCs2zTrw='

注意:该方案存在兼容性风险,若后续Google Maps更新内联样式内容,哈希会失效,需要重新添加新的哈希值,长期使用推荐nonce方案。


内容的提问来源于stack exchange,提问作者Jam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 15:45:00