使用Azure App Service内置认证时的Content-Security-Policy配置问题
解决方案:Blazor Server + Azure App Service认证 + Front Door CSP内联脚本拦截问题
核心问题是Front Door的静态CSP覆盖了App Service认证中间件自动生成的带动态nonce的CSP,导致内联脚本的nonce未被信任。以下是两种可行的解决方式:
方法1:让App Service管理带动态Nonce的完整CSP
这是最直接的方案,利用认证中间件的自动nonce注入能力:
修改Front Door配置
删除Front Door中覆盖Content-Security-Policy的规则;如果需要补充基础规则,将操作改为追加而非替换。在Blazor应用中配置CSP
- 安装NuGet包
NetEscapades.AspNetCore.SecurityHeaders简化CSP配置 - 在
Program.cs中添加CSP配置,兼容认证中间件的动态nonce:using NetEscapades.AspNetCore.SecurityHeaders; var builder = WebApplication.CreateBuilder(args); // 保留现有Azure AD/Easy Auth认证配置 builder.Services.AddAuthentication() .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")); // 配置CSP,启用动态nonce支持 builder.Services.AddCsp(options => { options.Policy = policy => { policy.BaseUri(s => s.Self()); policy.DefaultSrc(s => s.Self() .CustomSources("https://*.myapp.com", "wss://*.myapp.com", "https://dc.services.visualstudio.com/v2/track")); policy.ObjectSrc(s => s.None()); policy.ScriptSrc(s => s.Self() .CustomSources("https://*.myapp.com", "https://az416426.vo.msecnd.net") .Nonce()); // 自动绑定认证中间件生成的nonce policy.ImgSrc(s => s.Self().Data()); policy.StyleSrc(s => s.Self()); policy.FrameAncestors(s => s.Self()); policy.FormAction(s => s.Self()); policy.UpgradeInsecureRequests(); }; }); var app = builder.Build(); // CSP中间件需放在认证中间件之前 app.UseCsp(); // 保留现有中间件配置 app.UseAuthentication(); app.UseAuthorization(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run();
- 安装NuGet包
部署后,App Service认证中间件会自动为生成的内联脚本添加nonce,并将该nonce注入到CSP的script-src规则中,浏览器会信任带对应nonce的内联脚本。
方法2:保留Front Door静态CSP并追加动态Nonce
如果必须通过Front Door设置基础CSP规则:
调整Front Door响应头规则
将Content-Security-Policy的操作设置为追加,而非替换。确保App Service返回nonce片段
认证中间件默认会返回包含script-src 'nonce-XXX'的CSP片段,Front Door追加的静态CSP会与该片段合并,最终生成的CSP会包含完整的可信源和动态nonce,从而允许内联脚本执行。
验证方式
使用Chrome开发者工具的Security面板,查看Content-Security-Policy响应头,确认script-src中包含'nonce-XXX'字段,且内联脚本的nonce属性与该值匹配。
内容的提问来源于stack exchange,提问作者user18901997
相关产品推荐
相关产品推荐

