views:

281

answers:

1

Ok, Im really going to show my stupidity regarding the ASP.NET security model here but here goes.

I have a WCF web service and I have managed to hack my way around to having it pipe through my custom membership provider.

My membership provider overrides "ValidateUser" in which I attempt to load a user object with data from our SQL server instance. All good so far, I retrieve the creds, load the users object and return true if I don't hit any bumps in the road.

At this point, I would usually stuff the user object (or id) into session or actually just some state bag that's accessible for the lifetime of the request. The problem that I am hitting is that HttpContext is null at this point, even though Im using ASP compatability attributes.

What other options do I have at hand? Cheers, Chris.

EDIT:

Just to clarify what I want to do. I want to pass user credentials to be authenticated on the server, and once this has happened I would like to keep the the details of the authenticated user somewhere that I can access for the lifetime of the service request only. This would be the equiv of Http.Current.Items?

Is there any object that is instantiated per-request that I can access globally via a static property (i.e. in a similar way to HttpContext.Current)? I assumed that OperationContext was the this, but this is also null?

Can this really be such an uncommon problem? Send creds > retrieve user > stuff user somewhere for access throughout processing the request. Seems pretty common to me, what am I missing?

Cheers, Chris.

A: 

Basically, with WCF, the preferred best practice solution is to use per-call activation, e.g. each new request / call gets a new instance of the service class, and all the necessary steps like authentication and authorization are done for each request.

This may sound inefficient, but web apps, and in particular web services, ought to be totally stateless whenever possible. Putting stuff in a "state bag" just calls for problems further down the road - how do you know when to invalidate that cached copy of the credentials? What if the user exists your app but the cookie stays on his machine?

All in all, I would strongly suggest trying to get used to the idea of doing these step each and every time. Yes, it costs a little bit of processing time - but on the other hand, you can save yourself from a lot of grief in terms of state management in an inherently stateless environment - always a kludge, no matter how you look at it....

If you still insist on that kludge, you can turn on an ASP.NET "compabitility" mode for WCF which should give you access to HttpContext - but again: I would strongly recommend against it. The first and most obvious limitation is that this ASP.NET compatibility mode of course only works when hosting your WCF service in IIS - which I would again rather not do in production code myself.

To turn on the ASP.NET compatibility mode, use this setting in web.config:

<system.serviceModel>
   <serviceHostingEnvironment 
        aspNetCompatibilityEnabled="true"/>
</system.serviceModel>

and you need to decorate your service implementation (the class implementing the service contract) with a corresponding attribute:

[AspNetCompatibilityRequirements(RequirementsMode=
       AspNetCompatibilityRequirementsMode.Allowed)]
class YourService : IYourService

The AspNetCompatibilityRequirementsMode can be NotAllowed, Allowed or Required.

For more information and a more thorough explanation, see Wenlong Dong's blog post on ASP.NET Compatibility Mode

marc_s
Im happy without long lived state like sessions, but I just want to stuff my user object somewhere that I can access for the lifetime of the request. Basically all I want to do is pass credentials, load a user object form the database and hold that object somewhere for the lifetime of the request. What is the best approach?
Owen