Reputation: 19901
Pinging back to a webservice in ajax from the client keeps the user's session alive, I don't want this to happen.
For a website we're developing, we need the client to ping back (in js) to a webservice (ASMX) on the server (IIS7.5). This happens to let the server know that the user is still on the site, and hasn't browsed away to another site.
This is as our customer wants to let users lock records, but if they browse away to other sites, then let other people take over those locked records. Perhaps the distinction between the client being on the site but inactive and on another site seems unimportant, but that's kinda irrelevant, I don't get to write the UI spec, I just have to make it work.
My problem is this, the ping stops the user from being timed out on the server through the standard forms authentication timeout mechanism. Not surprising as there is that 30 second ping in the background keeping the session alive. Even though we want to know if the user is still on the site, we want the normal forms authentication timeout mechanism to be honoured.
I thought I might be able to fix this by removing the ASP.NET_SessionId and .ASPXAUTH cookies in the XMLHttpRequest that is the server ping, but I can't figure out how to do this.
This is how my web service & method are defined:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class PingWS : WebService
{
[WebMethod]
public void SessionActive(string sessionID)
{
// does stuff here
}
This is how I'm calling it in js (request is over HTTPS, :
$.ajax({
type: "POST",
url: "PingWS.asmx/SessionActive",
data: 'sessionID=' + aspSessionID + '}',
beforeSend: function (xhr) {
xhr.setRequestHeader('Cookie', '');
xhr.setRequestHeader('Cookie', 'ASP.NET_SessionId=aaa; .ASPXAUTH=bbb;');
},
dataType: "json"
});
I was trying with the setRequestHeader, but that just appends to the header rather than overwrites the header, and IIS is happy to ignore that junk I added.
I'm thinking maybe I should be trying to do this at the server end, someone take PingWS.asmx out of the loop so that it doesn't keep the session active, but I'm not sure how to do this.
Although the title of the question is focused on clearing the cookie in the header, I'd be super happy if anyone points out that I'm being really stupid and there is actually a much better way of trying to do what I'm doing.
I'm thinking at this stage maybe I need to add something to the webmethod that says how long this particular page has been inactive, and use that knowledge to timeout manually. That actually sounds pretty easy, so I think I'll do that for now. I'm still convinced that there must be an easy way to do what I originally wanted to do though.
I'm thinking I'm pretty screwed in terms of cookie manipulation here as both the .ASPXAUTH and ASP.NETSessionId cookie are HttpOnly, which means the browser takes them out of your hands, you can't access them via the document.cookies object. So I would say that leaves me with:
I know how to do 1. so I'll start there but 2. seems much cleaner to me.
Upvotes: 2
Views: 1779
Reputation: 19901
There is a server side answer. Basically you disable sliding timeouts on forms authentication, then manually slide the timeout yourself, and skip it for the ping.
Pretty easy for me as every page uses the same root Site.Master and all pages inherit from the same base class.
Summed up here: http://picometric.blogspot.com/2009/04/manual-sliding-expiration.html
Upvotes: 0
Reputation: 1038930
You could restrict the authentication cookie to a given Path:
<authentication mode="Forms">
<forms path="/admin" />
</authentication>
This way the authentication cookie will only be sent to the /admin
portion of your site and if you put your web service at the root you can ping it with AJAX without sending the cookie.
Another option is to simply host this webservice into a separate virtual directory.
Upvotes: 1
Reputation: 75844
As you're finding you're out of luck with client cookie manipulation (or clientanipulation of any kind). Manipulating headers might be possible but you'd have to intercept the traffic very early in the pipeline. I don't even know if it will be possible in the service itself but a traffic manager like Zeus could do it. I don't believe it's possible to configure the session engine in such a way as to ignore a given combination of endpoint and client request and although it should be possible to replace the entire session engine that will be undocumented and extremely time consuming I'd think.
Basically you need to manipulate traffic before it touches the service or you're not going to resolve this. Session was not designed to be variant.
Upvotes: 0