I think I've pared this down as far as I can. It happens only when using Forms Authentication and only seems to work in IE. So far, I've found that both Chrome and Firefox cause the issue. I have a very simple ASP page that increments a counter (stored in a session variable) on each page load. The page is named test.asp
and appears in my web root. Here are the contents:
<%
' Write the last value (obviously blank the first time)...
Response.Write "Last Num: " & Session("Num") & "<br>"
' Increment the counter...
Session("Num") = Session("Num") + 1
' Show the number we just saved...
Response.Write "This Num: " & Session("Num") & "<br>"
' Throw the session ID out there, too, to make sure it's consistent...
Response.Write "Session ID: " & Session.SessionID
%>
<form method="post" action="test.asp">
<input type="submit" value="Submit">
</form>
And I've stripped down my web.config
as much as possible while still reproducing the issue. Here are its contents:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
<system.web>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<authentication mode="Forms">
<forms loginUrl="test.asp" />
</authentication>
</system.web>
</configuration>
Pretty basic stuff here. I've set test.asp
as the "login" page and enabled runAllManagedModulesForAllRequests
. Things work as expected. All requests are redirected to test.asp
, as you'd expect. And test.asp
loads fine, except it for what happens next...
Here's how the page appears in IE (v11), Chrome (v44), and Firefox (v39) when loading initially and after submitting:
Internet Explorer 11:
Google Chrome 44:
Mozilla Firefox 39:
When I click [Submit]
, I'm obviously expecting the Last Num
value to be equal to the previous This Num
. But that only happens in IE. In Chrome, it seems to be doing an extra increment. And in Firefox, it seems to be doing two! To make things more confusing, after that initial submission, Firefox properly increments by 1 each time. Chrome, however, continues to double-increment with each submission.
These are default browser installations. No added extensions or special configurations. Cookies are enabled in all three browsers (the default). I can see the ASPSESSIONID
cookie using the developer tools of each browser. And, as you can see in the screenshots, the Session ID
is created on page load and stays consistent throughout the session.
If I continue submitting, the results are the same. IE continues to work properly. The other browsers continue to double or triple increment.
Anyone seen this issue before? Or see where I may have gone wrong here? I've tried specifying cookieless="UseCookies"
in the <forms>
section of the web.config
as well.
Edit 1 - Testing Elsewhere:
All of my testing to this point has been on my local PC: Windows 7 64-bit with IIS 7.5. Today, I connected to my eventual test server -- a Windows Server 2008 R2 box, also with IIS 7.5 -- and I get the same results there with my test page.
Edit 2 - loginUrl-related?
Using a new page, test2.asp
, with the same content (and given explicit anon access via a <location>
element in my web.config
) works fine. So it seems to be loginUrl
related? Maybe with every page request, it's calling the loginUrl
page behind the scenes? But again, with some connection to Chrome/Firefox...
Edit 3 - More Proof:
I decided to log the value of This Num
each time the page is executed. Here's what I'm seeing:
Internet Explorer:
8/4/2015 11:52:07 AM, Num=[1] Initial page load. One execution.
-----------------------------
8/4/2015 11:52:11 AM, Num=[2] All future submissions run once.
8/4/2015 11:52:16 AM, Num=[3]
8/4/2015 11:52:20 AM, Num=[4]
Chrome:
8/4/2015 11:34:58 AM, Num=[1] I get 2 executions on initial page load.
8/4/2015 11:35:00 AM, Num=[2] First execution (Num=1) appears in browser.
-----------------------------
8/4/2015 11:35:29 AM, Num=[3] Every submit causes page to run twice.
8/4/2015 11:35:29 AM, Num=[4]
-----------------------------
8/4/2015 11:35:49 AM, Num=[5]
8/4/2015 11:35:49 AM, Num=[6]
Firefox:
8/4/2015 11:36:25 AM, Num=[1] I get 3 executions on initial page load.
8/4/2015 11:36:25 AM, Num=[2] The first execution (Num=1) is the page
8/4/2015 11:36:25 AM, Num=[3] I see in the browser.
-----------------------------
8/4/2015 11:36:34 AM, Num=[4] All future submissions run once.
8/4/2015 11:36:43 AM, Num=[5]
8/4/2015 11:36:48 AM, Num=[6]
8/4/2015 11:36:53 AM, Num=[7]
Edit 4 - loginUrl Page Called on Every Request:
It seems any type of page request is causing test.asp
to execute behind the scenes, which increments the session variable. And that must be because it's the page identified by loginUrl
for Forms Auth. Combining the tests I did under edits 2 and 3, I granted anon access to a new test page (test2.asp
) that doesn't do anything special -- just loads a static page. Here it is:
<html><body>I'm test2.asp</body></html>
And then I monitored the log file that test.asp
appends to when it runs. Every time I requested test2
, I would get a new entry in the log. So every time I made a page request, test.asp
runs in the background (and increments the session variable). Here's how the log looked after three requests to my test2
page:
8/4/2015 12:20:57 PM, Num=[3]
8/4/2015 12:21:07 PM, Num=[4]
8/4/2015 12:21:14 PM, Num=[5]
test2.asp
doesn't do anything with the session variable (nor logging) but there's the proof. So, for some reason, on Chrome, it runs the loginUrl
page with each request. I think I can consider that to be proven. Now I just need a solution!
With the help of Fiddler, I was able to figure this out.
It seems both Chrome and Firefox make an additional request for your favicon.ico
, whether or not you've specified that you're using one in your HTLM page. Internet Explorer, on the other hand, doesn't bother.
This was a problem for me for a few reasons:
favicon.ico
was step 274.runAllManagedModulesForAllRequests
, so requests for icons, like all content, runs through Forms Authentication.<link>
to one and specify its location, Chrome and Firefox try to grab one from your web root. Forms Authentication (and my web.config) have my root locked down. The only file being served from my root is my loginUrl
page.Each time a request for favicon.ico
was being made, Forms Authentication was disallowing it and redirecting the request to my loginUrl
page, consequently causing my loginUrl
page to be executed twice and screwing up my session values. The following Fiddler screenshots show the proof.
Chrome seems to request the icon on every page request:
Whereas Firefox seems to request it twice initially, for some reason, but then gives up for subsequent requests:
So, the solution:
favicon.ico
file and place it in your web root.Allow anonymous access to it via a <location>
element in your root web.config
.
<location path="favicon.ico">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
Alternatively (probably the preferred method, since you can designate the name and location):
favicon.ico
file and place it in a public subfolder, like /img
.<link>
to it properly within your loginUrl
page.
<link rel="icon" href="/img/favicon.ico">