Readonly access to session in a web service call? - asp.net

We have a .net asmx web service that gets called from javascript (using ASP.Net AJAX), and requires access to Session.
[WebMethod(true)]
public string DoSomethingOnTheServer() { }
We're running into the problem of session being locked on a read/write request. Is there any way to mark a web service method as requiring read-only access to Session?
Thanks!

This is a really old thread, but i stumbled on it in my search for an answer to the same question.
I found the answer else where, and will leave it here for other internets in my place:
In Global.asax you can specify for each request, what access the request should have to the session object, and thereby if it should block or not.
private void Application_BeginRequest(object sender, EventArgs e)
{
// This will set the session to read only for asmx services
// This will make the asmx services non blocking for other requests as it doesnt lock the session object
if (Context.Request.Path.Contains(".asmx/"))
{
Context.SetSessionStateBehavior(SessionStateBehavior.ReadOnly);
}
}
This way asmx services always only have read only access to the session and will not block other requests

This http://msdn.microsoft.com/en-us/library/aa480509.aspx page seems to suggest that the answer is "no" - you cannot mark a WebSerivce as having EnableSessionState=ReadOnly.
If you are making simultaneous Web service calls from the same process, the requests will be serialized at the server so that only one will execute at any one time. Unlike .ASPX pages that have support for read-only access to the HttpSessionState object, which allows for simultaneous processing of multiple requests, there is no such capability with ASP.NET Web services. All Web method calls with sessions enabled have read/write access and will be serialized within each session.
Warning: That article is old (2002).

According to the MSDN documentation of the WebMethod Attribute there are several possible properties, so I'm not sure what the 'true' value in your WebMethod Attribute going to do.
Have you tried:
[WebMethod(EnableSession=true)]
According to this document that should give you full access to the session.

Related

Access HttpContext.Current.Session in Nancy Module

I've read a lot of answers saying to just use the built-in Nancy Session/User object, but this isn't an option in my case.
Using WCF I was able to access the ASP.Net Session["SomethingStuffedIntoSessionFromAWebForm"] by enabling aspNetCompatibilityEnabled in the web.config (other stuff had to been done too, probably), but I can't seem to figure out how to get a handle on the System.Web.HttpContext.Current.Session (or anything else in the current context) from within a Nancy module.
My 1st thought was to inject it in the bootstrapper but I can't even get a handle on the System.Web.HttpContext.Current.Session there either. Any ideas?
Edit
I ended up just stuffing an encrypted version of my desired session object into a cookie upstream and checking/validating against it in the module's BeforePipeline... not too crazy about this approach, but it suits my needs for now.
As far as I can tell, when a Nancy module handles a request, it bypasses the Asp.Net pipeline, so while I actually do have access to HttpContext.Current, Session is not populated.
Inherit IRequiresSessionState to enable Asp.net Session.
public class NancyAspHttpRequestHandler
: NancyHttpRequestHandler, IRequiresSessionState
{
}
and use NancyAspHttpRequestHandler in handler registration, this can be possible using Nancy.AspNet hosting.
This will solve the problem

Implementing Authorization in a Self Hosted SignalR Server accessed from Web

I'm looking for some guidance on how to implement authorization security for SignalR on a back end service running in a self-hosted (non-IIS) environment, that is called from a Web application. The backend app is basically a monitor that fires SignalR events back to the HTML based client. This all works fine (amazingly well actually).
However, we need to restrict access to the server for authenticated users from the Web site. So basically if a user is authenticated on the Web site, we need to somehow pick up the crendentials (user name is enough) and validation state in the backend app to decide whether to allow the connection as to avoid unauthorized access.
Can anybody point at some strategies or patterns on how to accomplish this sort of auth forwarding?
I am having similar issues here, as in my web app I use a simple cookie authentication system which uses an AoP style approach to check for any controllers with an attribute, then will get the current context (be it from the static HttpContext.Current or from the target invocation object depending on the type of interceptor) and then verify the cookie exists, it contains right data, then finally verify the token with the db or cache etc.
Anyway this approach can also be used for Signalr, although its a bit more long winded and you are using dependency injection. You would basically wrap the hub calls with the desired attribute, then set up your DI/IoC configuration to intercept these calls, then either get the hub instance within your interceptor and get the cookie (or your custom authentication mechanism) from the request, verify it is all valid or not, and if not then throw a new HttpException("403", "Not authenticated"); which should kick the user out and return back before it even hits your hub method, this way you can put the logic in one place (your interceptor, or a class the interceptor consumes) then just wrap any method that needs to use this authentication using your attribute.
I use Ninject and the interception extension, but most major DI frameworks these days have some form of IoC plugin/extensions, such as Autofac, Windsor, Spring etc.
If you were not happy going down the route of introducing DI and/or AOP to your current project, then maybe you could just create a custom hub instance which contains your authentication logic and then just use that in your hubs, so ok you will still be manually calling some authentication logic from within each hub method you want to protect, but its less code, so something like:
public class AuthorisableHub : Hub
{
private ISomeAuthenticationToken GetSomeAuthenticationTokenFromRequest(Request request) // probably a SignalR specific request object
{
// Get your token from the querystring or cookie etc
}
private bool IsAuthenticationTokenValid(ISomeAuthenticationToken token)
{
// Perform some validation, be it simple or db based and return result
}
protected void PerformUserAuthentication()
{
var token = GetSomeAuthenticationTokenFromRequest(Context.Request);
var isRequestValid = IsAuthenticationTokenValid(token);
if(!isRequestValid)
{ throw new HttpException(403, "<Some forbidden message here>"); }
}
}
public class MyFancyPantsHub : AuthorisableHub
{
public void TellAllClientsSomethingSecret(ISecret secret)
{
PerformUserAuthentication();
// Do stuff with the secret as it should have bombed the user out
// before it reaches here if working correctly
}
}
It is not perfect but would work (I think), also I am sure I once read somewhere that Hubs are newly instantiated for each request, and if this is indeed true, you could possibly just put this logic in your constructor if you want to apply the authentication to every action within the hub.
Hope that helps, or gives you ideas... would be interested in knowing how you did solve it in the end.
SignalR does not provide any additional features for authentication. Instead, it is designed to work with the authentication mechanism of your application.
Hubs
You should do authentication as you normally would and then use the Authorize attribute provided by SignalR to enforce the results of the authentication on the Hubs.
The Authorize attribute can be applied to an entire Hub or particular methods in the Hub. Some examples:
[Authorize] – only authenticated users
[Authorize(Roles = "Admin,Manager")] – only authenticated users in the specified .NET roles
[Authorize(Users = "user1,user2")] – only authenticated users with the specified user names
You can also require all Hubs to require authentication by adding the following method in the Application_Start method:
GlobalHost.HubPipeline.RequireAuthentication();
Persistent Connections
You can use the user object in the request to see if the user is authenticated:
request.User.IsAuthenticated

Access Forms Authentication from Separate HTTP Handler

I'm just reading about implementing my own HTTP handler for ASP.NET 4.0 and IIS7. This looks really cool. I want special processing for ZIP files and it seems like an HTTP handler is the perfect solution.
However, what's giving me trouble is that the handler must be in a separate assembly. So how can I access the rest of my application from this assembly?
Specifically, I'd like to determine if the user is authenticated and redirect them to the login page if they are not. But User.Identity.IsAuthenticated, etc. will not be available from my handler.
(Yes, I know there are ways to approach this without an HTTP handler but they don't seem appropriate for my specific needs.)
User.Identity.IsAuthenticated, etc. will not be available from my handler.
The ProcessRequest method gives you the current HTTP context from which you could determine if the user is authenticated:
public void ProcessRequest(HttpContext context)
{
if (!context.User.Identity.IsAuthenticated)
{
// the user is not authenticated
}
...
}

ASP.net web services

I am using a web service which sets the Thread.CurrentPrincipal object while logging in and soon later when another webmethod of the same web service accesses Thread.CurrentPrincipal, its different/resets
Can someone tell me if this is expected or can different webmethod calls from the same client can access the same Thread.CurrentPrincipal object
Thanks
As soon as you stop using a thread it goes back into the thread pool.
The next call will take a thread from the thread pool, but you have no control which one you get.
You need to send information about which user is making the call, with each request.
This is expected, every new web request is actually new thread. And every web request reset stuff like CurrentThread, CurrentCulture and so on.
What are you trying to do is authentication session. There are many possible solutions. But to suggest something I have to specify technology you use.
For example, ASP.NET ASMX Services can use Forms Authentication. Also they are aware about ASP.NET Session.
With WCF, you can enable ASP.NET support, so you will have same stuff like for ASP.NET ASMX Services. But you also can leverage on Windows Communication Foundation Authentication Service.
Anyways need more info from you.
If you are using the built-in ASP .NET authentication for your website and then just calling the web service from a web page, you may be able to enable session variables and user context information in the methods of the web service with a decoration. Like this:
[WebMethod(EnableSession=true)]
public void MyWebMethod()
{
string mySessionVar = HttpContext.Current.Session["sessionVar"].ToString();
IPrincipal currentUser = HttpContext.Current.User;
...
}
If that doesn't solve your problem, tell us what are you using the Thread.CurrentPrincipal object for (what you are pulling out of the Thread.CurrentPrincipal object). Perhaps there is another solution.

Access asp.net variables

I have a session variable that I want to access in a Silverlight 3 application. How can I do it in the best recommended way?
In the object tag in your Silverlight aspx host page:
<param name="initParams" value="myvar=<%=Session["myvar"] %>" />
then retrieve the value in app.xaml.cs
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new Page();
myvar = e.InitParams["myvar"];
}
Not the most secure way and as has been noted only work best for immutable session variables.
The other way which was already suggested was to expose the session variable using a WCF service. It all depends on how you want to retrieve the value, how secure you want the process to be, which of several ways you want to access the value and from where(in the web page or in the Silverlight app). I hope some of this makes some sense.
If it is a mutable value, i.e. changes after the session initialization, use an Ajax or WCF call to a service endpoint to get/set the value. The ScriptService or 'Ajax Enabled WCF' endpoint will both have access to the session.
If the value is immutable as the hosting page is being rendered, you could, and I don't suggest this, write it out as a JSON object to the hosting page.

Resources