WebOptimizer
WebOptimizer copied to clipboard
System.UnauthorizedAccessException: Access to the path 'C:\inetpub\wwwroot\mysite\myapp\obj\WebOptimizerCache' is denied.
This happens during IIS cold starts.
- dotnet core 5
- IIS
-
<PackageReference Include="LigerShark.WebOptimizer.Core" Version="3.0.304" />
-
<PackageReference Include="LigerShark.WebOptimizer.Sass" Version="3.0.43-beta" />
Startup - WebOpt Configuration
return services.AddWebOptimizer(pipeline =>
{
// Main css bundle (pre-minified files)
pipeline
.AddCssBundle(
"/css/bundle.min.css",
"/lib/datatables/css/dataTables.bootstrap4.min.css",
"/lib/datatables.net-buttons-bs4/buttons.bootstrap4.css");
// Main js bundle (pre-minified files)
pipeline
.AddJavaScriptBundle(
"/js/bundle.min.js",
"/lib/jszip/jszip.min.js", // Dependency for Datatables excel export Button
"/lib/pdfmake/pdfmake.min.js", // Dependency for Datatables pdf export Button
"/lib/pdfmake/vfs_fonts.min.js", // Dependency for Datatables pdf export Button
"/lib/jquery/jquery.min.js",
"/lib/jquery-validation/dist/jquery.validate.min.js",
"/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js",
"/lib/bootstrap/dist/js/bootstrap.min.js",
"/lib/datatables/js/jquery.dataTables.min.js",
"/lib/datatables-buttons/js/dataTables.buttons.min.js",
"/lib/datatables-buttons/js/buttons.html5.min.js",
"/lib/datatables-buttons/js/buttons.print.min.js",
"/lib/datatables.net-buttons-bs4/buttons.bootstrap4.min.js",
"/lib/datatables/js/dataTables.bootstrap4.min.js");
// Nested bundles would be great.
// https://github.com/ligershark/WebOptimizer/issues/159
// IE bundle up all the pre-minified stuff above, and then minify some additional files with WebOptimizer and concatenate it all together.
pipeline
.MinifyJsFiles("/js/site.js");
pipeline
.MinifyCssFiles("/css/site.css");
// Enable referencing .scss files directly in the browser (http://domain/a.scss)
pipeline.CompileScssFiles();
// Take our custom Bootstrap SCSS and compile+minify it.
pipeline
.AddScssBundle("/css/bootstrap.custom.min.css", "css/bootstrap.custom.scss")
.MinifyCss();
});
Startup - Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSecurityHeaders();
app.UseWebOptimizer();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCustomSerilogRequestLogging();
app.UseMiniProfiler();
app.UseEndpoints(endpoints =>
{
endpoints
.MapRazorPages()
.RequireAuthorization();
});
}
Error
Exception: System.UnauthorizedAccessException: Access to the path 'C:\inetpub\wwwroot\mysite\myapp\obj\WebOptimizerCache' is denied.
at System.IO.FileSystem.CreateDirectory(String fullPath, Byte[] securityDescriptor)
at System.IO.Directory.CreateDirectory(String path)
at WebOptimizer.AssetResponseStore.AddAsync(String bucket, String cachekey, AssetResponse assetResponse)
at WebOptimizer.AssetBuilder.BuildAsync(IAsset asset, HttpContext context, IWebOptimizerOptions options)
at WebOptimizer.AssetMiddleware.HandleAssetAsync(HttpContext context, IAsset asset, WebOptimizerOptions options)
at NetEscapades.AspNetCore.SecurityHeaders.SecurityHeadersMiddleware.Invoke(HttpContext context) in C:\projects\netescapades-aspnetcore-securityheaders\src\NetEscapades.AspNetCore.SecurityHeaders\SecurityHeadersMiddleware.cs:line 68
at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()
It appears that setting enableDiskCache
to false
fixes the issue. Does it make sense to do that?
Maybe better is to set cacheDirectory
to directory with read/write permitions for app.
I think the default for cacheDirectory
is invalid. It points into the web app's content root (If later fixed, I've found it in this commit
)
A production web application should not have write access on its own directory, that would open security concerns.
To add write access only to the default <contentRoot>/obj
folder would need the deployment set up properly.
That's unnecessary extra work.
Why not just use the web application's temp folder?
@nvirth Do web apps have temp folders they can write to by default in IIS?
I think yes. But I'm not sure. But then I can't remember setting up any folder credentials for HttpPostedFileBase
to work in the old ASP.NET MVC. That saves the uploaded files into a temporary folder - maybe it's the Temporary ASP.NET Files
folder somewhere, don't really know that.
Anyway, I just fixed the issue in my project with a custom MyWebOptimizerConfig : IConfigureOptions<WebOptimizerOptions>
implementation. In this I set CacheDirectory
to Path.GetTempPath()
. I applied it this way:
services.AddWebOptimizer(...);
services.Remove(services.Single(s => s.ServiceType == typeof(IConfigureOptions<WebOptimizerOptions>)));
services.AddTransient<IConfigureOptions<WebOptimizerOptions>, MyWebOptimizerConfig>();
@VictorioBerra Path.GetTempPath()
does not always work. On one of our new test servers, we've seen this log now: System.UnauthorizedAccessException: Access to the path 'C:\Windows\TEMP' is denied.