I am trying to ensure that stale images/js/css files in a cache will not be used after deploying a new version of an asp.net web application.
I'm currently looking in to the js aspect of this. First, ALL of my own scripts are registered through the System.Web.UI.ScriptManager with normal urls to js files. So, I've subclassed the ScriptManager and I tack a ?ver='x.x.x.x' on the end of the script url. I don't see any problem with that for my scripts with normal urls, however there are always a lot of ScriptResource.axd references and I am concerned about these scripts.
So, for example, lets say in my next version I update the AjaxControlToolkit dll. Will the scriptResource.axd urls be different from the urls used by the previous AjaxControlToolkit? The scriptResources.axd look pretty funky to me, so I am hoping they are generated with a hash of the assembly or something? I've been through a ton of literature on scriptResource.axd, but I haven't found anything on this topic. Anyone have any ideas?
Thanks for reading.
You're partially right. The format of resource URL is WebResource.axd?d=encrypted identifier&t=time stamp value. The "d" stands for the requested Web Resource. The "t" is the timestamp for the requested assembly, which can help in determining if there have been any changes to the resource.
In brief, the first parameter is encrypted assemblyName + "|" + resourceName value (by using internal Page.EncryptString method); the secondparameter is number of ticks of assembly was last written to date (by using File.GetLastWriteTime method).
So, using the next version or your assembly will change the resource URL (rebuild the assembly and/or change its version).
More information could be found here:
Working with Web Resources in
ASP.NET 2.0
WebResource.axd or how I learned to
love the embedded resource
Related
I am working on .Net(C#) application. It's a quite old application and has classic Asp pages, Web Forms and MVC pages. And using single page application concept to load all these pages. All of them have different-different CSS and JS based on business logic they have.
Now the problem is, every time after our release we face same issue that is CSS and JS caching. I know there are couple of ways to deal with this issue, the most common is adding a version and change this version with every release. But the problem is we have thousands of such links so updating all of then I don't find it a solution that we should opt.
Another approach what we thought of is, we can have a module that intercept all the resource requests and we update the link for each CSS and JS file and add some version (what I mentioned in above paragraph). But the problem I can see here is, this will make application slow because of checking and executing some string (File path) manipulation code for each resource requests.
I am sure I am not the only one who is facing this problem, so if anyone can share their experience and approach to handle this problem with minimum changes in code.
As #tim suggested adding query string to the files will help you.
Considering the volume of changes required at your end, I think preparing a rewrite rule for .js and .css files (with pattern matching) and injecting the query string to target URL (with permanent redirection) will help you.
solution for similar query is available here
Please note that, with each build you might need to tweak the configuration as necessary.
What might help: it isn’t necessary to include a version number in your files. It is sufficient if a versionnumber exists in your link.
You could use a (fake) querystring for that. So instead of linking to your css or js file like “style.css” you could link to “style.css?version=1.02”. This querystring part is ignored, but the browser thinks it’s a new file.
Maybe you can go through all of your links one time; make them serverside (in case of webforms) and add this versionpart serverside based on the version of your build. Then for your next releases the problem is solved..
I've been going over WAF findings in an ASP.NET application. WAF is ModSecurity with OWASP CRS. One of the findings is:
URL file extension is restricted by policy, Rule ID 920440
and it fired at files WebResource.axd and ScriptResource.axd.
I did some researching. I found that these files are HTTP Handlers and these are embedded in assemblies. I found said rule - it's a simple one, it just checks file extension and blocks request based on this. The .axd just happens to be one of the listed file extensions.
As I understood, these files might be connected with using AJAX (I might be wrong on this one). However, I didn't manage to find any reason/explanation over the internet why are these blacklisted by OWASP. The only piece of information that might give a clue was this question.
Why are .axd files blacklisted? Are they deprecated? Can these be listed as exceptions from the rule or maybe these introduce some actual risk? Finally, how can you modify ASP.NET application so it doesn't need these files?
Maybe too late to reply but there are several security issues including Oracle padding attack CVE-2010-3332, Telerik remote code execution CVE-2019-18935 and ... which all are related to axd files.
We have an ASP MVC 5 applications. We use bundles with optimization enabled by default. But we have heard several times from users, that they get errors, that we think are caused by old versions of user scripts. Their browsers somehow take scripts from cache, despite the fact, that we have edited that script files and bundles should be updated. The worst part of the problem is that we can't imitate or recreate this problem. We don't know how. We already have tried to make test-changes to scripts like adding some "console.log('test')" lines in order to see, if the browser takes the cached version, but everything was ok, the hash in the end of <script src="....?v='hash'"> changed and the browser took the newest version from first time. I should mention, that our site is a single page application. Don't know, maybe its somehow related with the problem.
Have you faced this kind of problem?
There's not enough information here to give a definitive answer. The bundler detects changes in files and will regenerate the bundle along with the link to that bundle, which will include an updated query string param. Since the query string is part of the URI, it's considered a totally different resource at this point, and the browser should fetch it again, because there is technically no cache available. The only logical reason this would not occur is if the HTML with the link to the bundle is not being updated. This can happen if you're using OutputCache or otherwise caching the HTML document. It can also happen if the client's browser is aggressively caching the HTML document. Unfortunately, there's not much you can do about that, as the client browser ultimately has control over what is or is not cached and for how long.
That said, given that this is a single page app, it's very possible that it's also including a cache manifest. This manifest will very often include the HTML file itself, and the browser will not refetch any file in the manifest unless the manifest itself is updated.
I am curious to know how asp.net bundling works.
I know we've to add the all scripts and css and images to the bundle so that browser will initiate single request for all the resources.
I 've some confusion how the pages will refer these bundled resources from client browser.
Let's take a look at what happens when we use the bundling in System.Web.Optimization.
In this example I used the "Empty ASP.NET MVC 4 template" and grabbed the latest "Microsoft.AspNet.Web.Optimization" package from nuget.
I then proceeded to register 2 javascript files. One for jquery and another for bootstrap.
public static void RegisterBundles(BundleCollection bundles)
{
var javascriptBundle = new Bundle("~/bundles/javascripts")
.Include("~/Scripts/jquery-{version}.js")
.Include("~/Content/bootstrap/js/bootstrap.js");
bundles.Add(javascriptBundle);
}
Now that we have our setup done, let's see what happens when we view the page.
You can see that both the javascript files were just included as we would normally do. This is what happens when you have the "debug" flag set in your web.config.
Let's turn this to false and see what happens now.
Now what we see is a single reference was added but with a very unique looking location. By clicking on it, we see that it spits out a minified and combined version of both of the javascript files that were referenced in our bundle.
This funny query string parameter v=loMmcAiXrKwMoVsM8Ok8Q5jVmuFQUI3fiiRVJQC33Hs1 is a reference to our content and we can see that no matter how many times we hit the website, it's going to stay the same. (i.e. refreshing multiple times).
Let's see what fiddler says about the reference to our javascript files.
We can see that the response is cachable. The cache expiration has been set for "Wed, 26 Mar 2014 06:49:06 GMT". Almost a year from today.
Subsequent requests to the resource will get read from the browser's cache.
"This HTTP/304 response indicates that the existing cached response remains fresh. Cache-lifetime headers on a HTTP/304 response may be used to update the cached response's freshness."
If you require any more information, see also http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
In my research, I found 2 ways to do them.
Both required modifications to the Application_BeginRequest procedure in the Global.Asax, where you would run your code to do the actual URL mapping (mine was with a database view that contained all the friendly URLs and their mapped 'real' URLs). Now the trick is to get your requests run through the .NET engine without an aspx extension. The 2 ways I found are:
Run everything through the .NET engine with a wildcard application extension mapping.
Create a custom aspx error page and tell IIS to send 404's to it.
Now here's my question:
Is there any reason one of these are better to do than the other?
When playing around on my dev server, the first thing I noticed about #1 was it botched frontpage extensions, not a huge deal but that's how I'm used to connecting to my sites. Another issue I have with #1 is that even though my hosting company is lenient with me (as I'm their biggest client) and will consider doing things such as this, they are wary of any security risks it might present.
`#2 works great, but I just have this feeling it's not as efficient as #1. Am I just being delusional?
Thanks
I've used #2 in the past too.
It's more efficient because unlike the wildcard mapping, the ASP.NET engine doesn't need to 'process' requests for all the additional resources like image files, static HTML, CSS, Javascript etc.
Alternatively if you don't mind .aspx extension in your URL's you could use: http://myweb/app/idx.aspx/products/1 - that works fine.
Having said that, the real solution is using IIS 7, where the ASP.NET runtime is a fully fledged part of the IIS HTTP module stack.
If you have the latest version of IIS there is rewrite module for it - see here. If not there are free third party binaries you can use with older IIS (i.e. version 6) - I have used one that reads the rewrite rules from an .ini file and supports regular expression but I cant remember its name sorry (its possibly this). I'd recommend this over cheaping it out with the 404 page.
You have to map all requests through the ASP.NET engine. The way IIS processes requests is by the file extension. By default it only processes the .aspx, .ashx, etc extensions that are meant to only be processed by ASP.NET. The reason is it adds overhead to the processing of the request.
I wrote how to do it with IIS 6 a while back, http://professionalaspnet.com/archive/2007/07/27/Configure-IIS-for-Wildcard-Extensions-in-ASP.NET.aspx.
You are right in doing your mapping from the database. RegEx rewriting, like is used out of the box in MVC. This is because it more or less forces you to put the primary key in the URL and does not have a good way to map characters that are not allowed in URLs, like '.
Did you checked the ASP .Net MVC Framework? Using that framework all your URLs are automatically mapped to Controllers which could perform any desired action (including redirecting to other URLs or controllers). You could also set custom routes with custom parameters. If you don't have seen it yet, maybe it will worth the look.