Is it possible to change the web.config file without giving all the users on the site a new session?
You can move the volatile portions of the web.config into external files and then set up IIS to not restart applications when those files change.
In the example below, application and connection-string settings have been moved to another file, outside of the web.config.
<?xml version="1.0"?>
<configuration>
<appSettings configSource="appSettings.config"/>
<connectionStrings configSource="connections.config"/>
</configuration>
Once that's done, you can make changes to app settings (or whatever else you put in the external file) without editing the web.config.
You can also visit the machine.config and play with the restartOnExternalChanges attribute, but this should be used with caution as it could have unintended consequences. Some sections, such as app-settings, already have this set to "false".
<section name="appSettings" restartOnExternalChanges="false">
More details are available in this OdeToCode article.
If you don't use InProc session state, then your sessions should persist across application restarts.
sessionState Element (Including notes on configuring SqlServer mode.
Related
I have an ASP.NET MVC5 website in development which I will shortly need to deploy to an IIS8 webserver. I'm trying to get the security model for the web.config file right, and in particular I want to:
Prevent secrets in the web.config file being exposed in my source control system
Protect the deployed web.config from prying eyes (I don't own the server).
From searching on SO and other sites I can see that there are specific tools/techniques to address each scenario:
'Included' sections in web.config that do not get saved to the SCCS.
Encrypted web.config files. Or encrypted sections of the file to be more precise.
I'm fine with both of those, but I can not for the life of me see how to combine the two techniques to solve both problems simultaneously. Is it possible to encrypt an external section? Is this even the right approach given that many of the answers are several years old now and address older versions of ASP.NET/MVC.
I can't be the first do want to do this so I'm sure I'm missing something obvious.
It has been suggested that this might already be answered here, however that question is about encrypting sections in the main web.config file, and I am asking about encrypting external sections. By that I mean sections that are 'included' using the configSource XML attribute.
It's probably bad form to answer ones own question, but I had a flash of inspiration and after a couple of hours of experimentation I have it working how I want.
The bit I had got all wrong was that I was trying to encrypt the external files. It does not work like that. Here's how it does work, at least, this is how it works for me on an IIS8.5 and ASP.NET v4.0.30319 server.
ConnectionStrings
Create the connectionStrings section in a separate file, e.g. Web.connectionStrings.config:
<?xml version="1.0"?>
<connectionStrings>
<add name="MyConnection" connectionString="{your connection string here}"
providerName="System.Data.SqlClient" />
</connectionStrings>
Ref this file from web.config:
<connectionStrings configSource="Web.connectionStrings.config" />
Make sure the external file is not under source code control so it does not get uploaded to your SCCS.
Deploy BOTH files, either as part of your deployment process or deploy the secure file manually if you're really paranoid.
Encrypt the connectionStrings section of the web.config normally, using the aspnet_regiis.exe command mentioned in the article mentioned by Afzaal. This process actually encrypts the contents of the Web.connectionStrings.config file and leaves the web.config file unchanged. You need to leave the external file in place but as it is now encrypted this is quite safe.
appSettings
Create your security-critical settings in a separate file, e.g. Web.appSettings.config.
<?xml version="1.0"?>
<appSettings>
<add key="wc1" value="web.app.config1" />
<add key="wc2" value="web.app.config2" />
</appSettings>
Ref this file from web.config:
<appSettings file="Web.App.config">
{other non-secure appSettings}
</appSettings>
Again, ensure the secure file is not under source control, and deploy both files to the production server.
Encrypt the appSettings section of the web.config file.
Unlike the connectionStrings section, this does not alter the external file at all. Instead, settings from both web.config and the external file are merged (external file takes precedence if duplicate keys are encountered) and are stored in an encrypted form in web.config.
At this point you can remove the Web.appSettings.config file as its contents are now incorporated into the main file.
Points to note:
If you introduce another Web.appSettings.config file at a later time, and restart the site, the contents of that file will override the encrypted settings in web.config. This may or may not be useful. When you remove the file and restart the site, the settings revert to the encrypted ones again.
If you decrypt the appSettings section, ALL the current settings are written back into the main web.config file, including those that originally came from the external file. You'll need to remember to remove them if you're just changing a setting and then re-encrypting the file again.
I have a custom session provider that stores data in a DB, so fetching session state is not a cheap operation. I have also runAllManagedModulesForAllRequests="true" in my web.config, so sessions are inicialized for every request to an image.
So, I am striving for turning off session state for directories with static resources. Unfortunately, setting <sessionState mode="Off" /> for a folder does not work as this is application-level option.
I could handle this in the code of my custom session provider, but I am wondering if there is some cleaner, more declarative solution.
Edit: <pages enableSessionState="false" /> does not seem to help as it is probably related to ASP.NET pages and controls only.
I don't think that is possible, think about it as session is provided for the whole application, and you just can say at this folder i have and at that i don't, all you can do is to custom code the costly operation of your provider to not run according to certain conditions, place that correctly in your page life cycle.
I ran into the same problem trying to do WebServices with cookieless sessions. I solved it with using a symbolic link. Here are the steps:
1) Make your subdirectory its own application in IIS
2) put this in the subdirectory web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<sessionState mode="Off" />
</system.web>
</configuration>
3) Create a symbolic link to redirect BIN to your own BIN. In my example the subdirectory was only 1 level below my main application. So I did this command from the subdirectory:
mklink /D bin ..\bin
That's it. It will load assemblies from your main BIN directory, and inherit all its other settings from your main application.
Current installation
I have two web applications app_A and app_B (same app with app_A but for test purposes) under IIS default website. A domain www.mydomain.com that points to the server needs to access app_A. That can be done by changing the physical path from \inetpub\wwwroot\ to \inetpub\wwwroot\app_A.
The second application should be access under www.mydomain.com/app_B/
Problem
When accessing www.mydomain.com/app_B/ because it's now a sub-directory of app_A it sees the web.config from app_A and I got error like "duplicate entries in web.config" when accessing the www.mydomain.com/app_B/ application. I can eliminate the errors by using the tag to remove first and declare again the entries in app_B web.config.
Questions
Is there any other way to make the installation in order app_A would be access from www.mydomain.com/ and app_B from www.mydomain.com/app_B without messing the web.config files as described above?
For the current installation, is there a way to set something on IIS in order for app_B not to see at all web.config from app_A because is a subdirectory?
For the current installation, do you see any real problems (possibly on security) by using the remove tag for the app_B application?
For the current installation I observer a strange behaviour. If I login to app_A and app_B and logout from app_A it also logout from app_B (not always). I am using Active Directory for authentication. Do I need to change something in app_B's web.config in order to say that it's totally different application?
I know this is an old question and you might have found out the solution. I am replying in case you need an answer.
There are two ways to avoid merging of parent’s config file and child’s config file. Either you can add
inheritInChildApplications="false" Tag in the parent’s config file. For example:
<location path="." inheritInChildApplications="false">
<connectionStrings>
</connectionStrings>
</location>
Or
you can add "Remove" tag or "Clear" in child’s config file to clear the parent’s settings.
Also, I don’t see any security threats by clearing parents settings.
By any chance are you using same cookie name in authentication for parent and child applications? If this is the case, once you login to child application, the cookie generated by the parent application will be overridden. Try specifying name of the cookie for at least one of the application.
According to Ultra-Fast ASP.NET: Chapter 3 - Caching:
Files that the browser retrieves from the server should be stored in
the browser’s cache as long as possible to help minimize server
round-trips.
But how does IIS know what a static content actually is and is not?
Is it just images, CSS, JS and not ASPX, ashx...?
Where can I see in IIS what is already considered to be static and what is not ?
What about the scenario where a page has been declared with <%# OutputCache header (without location)? Are the images, CSS and JS source files inside of it also being output cached with the same properties?
As a best practice, I should set one year into the future as the maximum expiration time. I should use that as the default for all static content on the site
So I did this :
But later, after pressing OK, I can't find any summary menu which shows me: to whom I already put a response header (in this case: the css folder).
Currently, in order to see that css folder has been applied with response headers - I have to go to the css folder again --> Http Response Header-->Set Common Headers --> and then I see it. It isn't written in the web.config.
But if I do it for a file (Login.aspx for example): I do see it in web.config:
<configuration>
<location path="Login.aspx">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseExpires" cacheControlMaxAge="1.00:00:00" httpExpires="Fri, 15 Feb 2013 00:00:00 GMT" />
</staticContent>
</system.webServer>
</location>
</configuration>
I understand your situation. Sometime its confusing how IIS handles a file. Its also different for IIS 6 vs IIS 7 and different for Classic App Pools and Integrated mode app pools. My experience is mostly with Integrated App Pools on IIS 7.5, so thats the environment I can comment on most accurately.
First Question
But how does IIS knows what is actually a static content and what is
not?
Is it just images , css , js and not ASPX , ashx...?
Where can I see in the IIS what is already considered to be static and
what not ?
You can inspect the list of file handlers in IIS by navigating to your website and then click 'Handler Mappings'. By default these are inherited from the .Net base web.config which is in a different location depending on your .Net framework version.
C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config
If a file being requested isn't already explicitly mapped to another handler it falls to a catch all handler (*) as the last option (System.Web.DefaultHttpHandler) which determines if it is a static file or a directory browsing request. So Static files are simply files not bound to another handler already. For example you'll see that *.aspx is already mapped to System.Web.UI.PageHandlerFactory prior to this default handler. So its going to be processed by that handler and not be considered a static file. If you removed that mapping you could technically serve *.aspx as a static file if you really wanted to (just for proof of how it works).
But you can also explicitly list a file type as a static file by adding an entry in your web.config's httpHandlers section mapping the file extensions to System.Web.StaticFileHandler in IIS. For example:
<configuration>
<system.webServer>
<handlers>
<add name="StaticHandler" verb="*" path="*.zip" type="System.Web.StaticFileHandler" preCondition="integratedMode" />
</handlers>
</system.webServer>
</configuration>
This example is using the <system.webServer> config section, so its for an App Pool running in Integrated Mode.
Second Question
What about the scenario where a page has been declared with <%#
OutputCache header(without location) . does the images,css,js src
files inside of it , are also being output cached with the same
properties?
No. Because the page is being server as a separate request (maybe even by a separate handler) it can have totally different cache headers/hints. The host page and the resources it may use are not related from a caching perspective.
In fact you may even want to have a shorter cache period for *.html and a longer cache period for *.jpg or *.png? Something to consider.
Third Question
As a best prcatice , I should set one year into the future as the
maximum expiration time.I should use that as the default for all
static content on the site
Hmm... I might not go as far as one year. How about one month? I would set a global policy like this:
<configuration>
<system.webServer>
<staticContent>
<!-- Set expire headers to 30 days for static content-->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
This is the same as the sample you showed above, but is not inside a <location> element, instead it is right in the root <configuration> element so it is the default policy. Again this is for an App Pool running in Integrated Mode. Sometimes you also need to turn on:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<!-- stuff -->
</modules>
</system.webServer>
<system.webServer>
This just makes sure that static files are processed through the managed static file handler which respects the above configuration elements.
Edit to Address Comments
The documentation for the configuration dialog you posted above is located here: Configure the HTTP Expires Response Header (IIS 7)
Apparently these settings are saved in C:\Windows\System32\inetsrv\config\applicationHost.config
I do not have IIS7 and personally develop on IIS 7.5 now. So please post a comment if you can verify this location is accurate!
The static content is the one that IIS is read and send to the browser with out any processing. There you can setup IIS to include some Cache-Control Header to cache it on clients browser computers.
You can do that ether by direct setup IIS, ether by commands on web.config as you say. The commands that you add on web.config and concern the IIS, did not have to do with asp.net it self, but the IIS, and IIS saves his configuration on a different file, so when you change that cache control headers direct on IIS you do not see them on web.config.
Now for the static content like images, CSS, JavaScript, and other similar files they say that you can follow the "never expire" policy by adding 10 years expire.
The issue here is that if you can not change the content of the static file, if for example you cache a javascript file with 10 years, and you make a small change on it, then you need ether to change the file name, ether to add some parameter at the end of it.
Now the <%# OutputCache on a control is referred to the server cache and not to the client, and what is actually do is to cache the render of the control on the server so the next time you ask it to not lose time to renders it again but read it from cache - is still send it to the browser.
And you can also read this answer for some more: What are difference between IIS (Dynamic and Static) cache,OutPutCache and browser cache
if it is cached, what happens if I use multiple web.config in multi-level folders
They all get cached.
Configuration is read once, at startup. With web.config, IIS watches for file changes and restarts the application.
OK, so ya'll are missing a KEY feature in the Web.Config file's area.
Yes, web.config is cached and changing contents of the file will restart your web app. And, all your connected users will not be happy, too, because they'll need to "reconnect" a-new, possibly losing desired information.
So, use an EXTERNAL custom file for your AppSettings, as follows:
<appSettings configSource="MyCustom_AppSettings.config"/>
Then, in the file MyCustom_AppSettings.config file, you have your settings, as such this example has:
<appSettings>
<!-- AppSecurity Settings -->
<add key="AppStatus_Active" value="Active"/>
<!-- Application Info Settings -->
<add key="AppID" value="25"/>
<add key="AppName" value="MyCoolApp"/>
<add key="AppVersion" value="20120307_162344"/>
</appSettings>
Now, if you need to add, change, or remove an AppSetting, when you change it in this file the change is nearly instant in your web-app BUT (and here's the BEST part), your app DOES NOT RESTART!
Everything stays kosher except those settings you've added/modified/removed in the external .config file.
And, yes, the same thing can done for the section as follows:
<connectionStrings configSource="MyCustomApp_ConnectionStrings.config"/>
and the file MyCustomApp_ConnectionStrings.config has all the connection strings you need. Change a connection string in the external .config file and it starts getting used right away and with no web-app restart.
The configSource setting(s) are great when you need to deploy to development, testing, and production on different boxes and need settings pertinent to that given box/environment.
So, now ya know (something that's been around for 7+ years).
It's That Simple. Really.
KC
Web.config (excluding external config files) is read when the application loads. Some config settings have a cascading behavior. For example, the system.web/authorization section can be overridden by configs at deeper levels.
ASP.NET monitors the web.config for changes. When it changes, the web application is forced to restart. Moral is that web.config settings are cached for the life of the application.