This project is read-only.

FilterSession

Feb 5, 2008 at 7:09 PM
Hi Tiago,

How does the FilterSession object work? Is this supposed to be analagous to an ASP.NET session, i.e. a place where I can persist data between requests? Or is it just for holding data as the current request bounces from event to event? Because it seems to be the latter, but I just wanted to make sure.

Thanks,

Jeff
Feb 7, 2008 at 5:05 PM
Hi Jeff,

For the ISAPI Filter (C/C++) author, the FilterSession is the pFilterContext element. Its associated with each TCP/IP established session.

For the Filter.NET author, the FilterSession works the same way as a cookie stored in the browser memory (it may resemble the ASP.NET cookie). I say browser memory, because when coookies are stored in the browser memory, they are associated with the browser instance (iexplore.exe), whereas a disk cookie is associated with all browser instances running on the client computer.

Hope it helps,
Tiago Halm
Feb 11, 2008 at 6:20 PM
Thanks Tiago. So the FilterSession is something that can persiste data across requests?
Feb 11, 2008 at 8:48 PM
Hi Jeff,

Yes, the FilterSession persists data across requests from the same TCP/IP connection. In other words, it persists data across requests coming from the same browser session or window as you may want to call it.

In HTTP, all requests coming from the same browser session (or TCP/IP connection) are sequencial (or pipelined in some instances). IIS makes sure that all requests coming from the same source address:port (ex: 10.0.0.10:24123) are associated with some data which Filter.NET exposes as FilterSession. Until the TCP/IP session is dropped by either side, you're guaranteed that if the next request comes from the same address:port the data you've put on FilterSession in the last request is still there.

Tiago Halm
Feb 12, 2008 at 2:46 PM
OK, that's what I figured. But, I'm guessing that since there is one instance of a Filter.NET module per app pool (app domain) in IIS, then anything I set in the FilterSession is only available inside that same app pool, even if requests from the same IP/port might be going to another app pool? A problem I have encountered is that on my web site, I have three app pools, and thus one Filter.net filter in each, which was fine, until I needed to basically broadcast an action that occurred in one filter.net instance to other instances. I can obviously set a cookie in the headers, but I was looking for something a little more elegant.

Jeff
Feb 12, 2008 at 5:53 PM
:)

That is one of the reasons why Microsoft adopted a different strategy for sessions with ASP.NET, allowing a session (something that in ASP was only available InProc) to be stored InProc, StateServer, SQLServer or Custom.

By the same token, a good alternative for your scenario is to store the browser related data in a shared storage like a database. ISAPI Filters are DLLs, so there is a separate instance in each process (executable). If you want to share data between ISAPI Filter instances you need a central storage reachable by each instance. How do you relate the data stored with the browser session? Thats where cookies come in, which can contain a simple reference (like a GUID) which allows you to point to the correct data in the database associated with the browser.

Now, lets discuss the cookie creation. What is the scope of the data stored? You can have the data associated with every single browser instance of the client, or you can have the data associated with a specific browser instance of the client. That should be the difference between creating a disk cookie or a session cookie. If you choose a session cookie, then remember that the client TCP/IP connection (session) terminates when the EndOfNetSession event occurs. This is the last event called when the TCP/IP connection is dropped (ex: the client closes the browser). This event allows you to clean the data stored in the database related to the client. Otherwise you can always clean the data in an "end of day clean up process".

Let me know if all this makes sense.

Tiago Halm
Feb 13, 2008 at 12:50 AM
Well, I thought about saving this data in a SQL database instead of the browser cookies, but I untimately decided against it, because I did not want to incurr a database hit on every request, as my scenario is as follows:

- My filter.net module injects user rights information for the current logged on user (access levels, application access, etc) into the HTTP headers. Obviously it must do this for every request, so my various asp and aspx pages can access the headers.

- It is also possible for a user to impersonate another user. This is where I am using the cookies. I must store information that the current logged on user is impersonating another user. And when the user crosses into a web app that might be running in another process, something needs to tell that process the user is impersonating someone else (i.e. the cookies). So on every request I must check my "impersonation flag" to see if I have to inject information for the logged on user, or the impersonated user, into the header. If I were storing my impersonation flag in a SQL database, I'd be hitting the database every request, and that's not something I want to do unless I absolutely have to.

So, unless I'm missing something, I don't see a "cookies" collection in Filter.NET. So I was trying to inject the cookies directly into the HTTP header using the Set-Cookie header. I was able to inject a session cookie like this (as I don't want the cookies persisting in anyway on the user's computer), but I was wondering if you knew how to remove the cookie then? I tried to use the Set-Cookie header to set the same cookie value to blank, but that didn't work. I know the cookie will be cleared when the session ends, is there a way to end the session in Filter.Net, i.e. Session.Abandon in ASP?

Thanks,

Jeff
Feb 13, 2008 at 11:46 AM
Hi Jeff,

Filter.NET does not have a cookie object, so for now its something that must set in raw mode, as you mentioned, via the http header Set-Cookie.

As for the session established between the browser and IIS, when the browser hits VDir1 on AppPool1, and next it hits VDir2 on AppPool2, the TCP/IP connection established is still the same (10.0.0.10:24123 => youriis:80). This happens because its not the AppPool that has a socket listening, its the kernel (HTTP.sys) and knows how to route the request details to the appropriate AppPool.

Since Filter.NET runs in each AppPool, there is no simple way to transfer the data stored between the 2 processes. When I mentioned EndOfNetSession above, this event is only called when the TCP/IP connection is in fact dropped or closed, not when the browser "switches" AppPool in the backend due the association of VDirs with AppPools.

In order to delete the cookie header (which is what you ultimately want to do when trying to clear its value) you can set its value to '\0' as mentioned in http://msdn2.microsoft.com/en-us/library/ms525099(VS.85).aspx.

I understand the database hit, and agree that would be a performance hit, but where do you fetch the information regarding "user rights information for the current logged on user (access levels, application access, etc)" which you inject as custom http request headers?

Tiago Halm
Feb 14, 2008 at 3:42 AM
I get the user rights information from an LDAP store, and it is cached in process after the first request, until the user either logs out or the session ends. I was able to get the cookie transfer working, so thanks again for your help.

Jeff