Need help understanding locking in ASP.NET - c#

I'm having some trouble understanding the basic concepts of locking in a multi-user / web application.
When a user gets authorized by our federation, he'll return with a username claim, which we'll then use to retrieve some extra info about him like so:
var claimsIdentity = (ClaimsIdentity)HttpContext.Current.User.Identity;
if(!claimsIdentity.HasClaim(CustomClaims.UserId)) //If not set, retrieve it from dataBase
{
//This can take some time
var userId = retrieveUserId(claimsIdentity.FindFirst(ClaimTypes.NameIdentifier));
//Because the previous call could take some time, it's possible we add the claim multiple time during concurrent requests
claimsIdentity.AddClaim(new Claim(CustomClaims.UserId, userId));
}
As indicated in the code, having duplicate claims isn't really what I'm looking for, so I thought I'd lock everything around the check whether the claim exists or not:
private static readonly object _authorizeLock = new object();
...
lock(_authorizeLock)
{
if(!claimsIdentity.HasClaim(CustomClaims.UserId)) //If not set, retrieve it from dataBase
{
...
}
}
However, this doesn't feel right. Wouldn't this lock be for all incoming requests? This would mean that even authorized users would still have to "wait", even though their info has already been retrieved.
Does anybody have an idea how I could best deal with this?

Answer 1:
Get over it and live with duplicate entries.
Answer 2:
If you have sessions turned on you get implicit locking between requests from the same user (session) by accessing the session storage. Simply add a dummy
Session["TRIGGER_SESSION_LOCKING_DUMMY"] = true
Answer 3:
Implement some custom locking on an object indexed by your Identity. Something like this
lock(threadSafeStaticDictionary[User.Identity.Name]) { ... }
Answer 4:
Lock on the Identity object directly (which should be shared since you get duplicates) (though it is not recommended)
lock(User.Identity)

Related

Unique Lock object per web request

I'm building a WCF translation service. The service uses google translat's web api.
To avoid re-fetching commonly searched queries, the service keeps a memory cache of the last searches.
The search function first checks the cache, and only then puts out a request to google.
Last important detail - every time a request arrives, I construct a string to be it's key - it's comprised of the search term, and the two languages name codes - so it is unique per specific search.
The question is this:
Suppose two exact request's arrive at the same time, I would like to lock the second one out of the whole search function, so that when it enters it will find the search result that was already entered to the cache by the first one. If a different request arrives, I want to let it in.
My idea was to put a lock using the string I constructed, as it is unique per exact search (same search term, same languages). Will this give the result I described?
Thank for reading this far (:
See the code example below - and again thanks!
public async Task<TranslationResult> TranslateAsync(Langueges From, Langueges To, string Content)
{
string key = Content + From.ToString() + To.ToString();
lock(key)
{
//look for the search result in the cache
//if not found, request from google and store result in the memory cache
}
}
Something like this?
// this cache is probably going to be the application level cache in asp.net
// but using Dictionary as an example in this case
Dictionary<string,TranslationResult> cache = new ...
private static object syncRoot = new Object();
if (!cache.ContainsKey(key)
{
lock(syncRoot)
{
// this double checks is not a mistake.
// the second request would check for existence of
// the key once it acquire the lock
if (!cache.ContainsKey(key) {
// send request to google then store the result
}
else {
return cache[key];
}
}
}
else
{
return cache[key];
}
I don't think you'll get the behavior that you're looking for: the variable "key" will always be a newly created object and the current thread will always be granted the lock right away. I don't believe string interning will be in play here because the "key" variable is not a literal. If "key" were an interned string, then it might work like you want, but that would be a strange side-effect.
What to do? Consider using the ConcurrentDictionary.GetOrAdd method. Your "key" variable will become the key argument. If the key is not in the cache, then the valueFactory will be called. Your valuefactory implementation should send the call to Google. This is ConcurrentDictionary is thread-safe, so no explicit locking is needed on your part.
if two exact request's arrives at the same time then returns one of them with orginaly :)
You can know which is not trunslated then send it again. i made this before like this

ThreadStatic and ASP.NET

I've got a requirement to protect my business object properties via a list of separate authorization rules. I want my authorization rules to be suspended during various operations such as converting to DTOs and executing validation rules (validating property values the current user does not have authorization to see).
The approach I'm looking at wraps the calls in a scope object that uses a [ThreadStatic] property to determine whether the authorization rules should be run:
public class SuspendedAuthorizationScope : IDisposable
{
[ThreadStatic]
public static bool AuthorizationRulesAreSuspended;
public SuspendedAuthorizationScope()
{
AuthorizationRulesAreSuspended = true;
}
public void Dispose()
{
AuthorizationRulesAreSuspended = false;
}
}
Here is the IsAuthorized check (from base class):
public bool IsAuthorized(string memberName, AuthorizedAction authorizationAction)
{
if (SuspendedAuthorizationScope.AuthorizationRulesAreSuspended)
return true;
var context = new RulesContext();
_rules.OfType<IAuthorizationRule>()
.Where(r => r.PropertyName == memberName)
.Where(r => r.AuthorizedAction == authorizationAction)
.ToList().ForEach(r => r.Execute(context));
return context.HasNoErrors();
}
Here is the ValidateProperty method demonstrating usage (from the base class):
private void ValidateProperty(string propertyName, IEnumerable<IValidationRule> rules)
{
using (new SuspendedAuthorizationScope())
{
var context = new RulesContext();
rules.ToList().ForEach(rule => rule.Execute(context));
if (HasNoErrors(context))
RemoveErrorsForProperty(propertyName);
else
AddErrorsForProperty(propertyName, context.Results);
}
NotifyErrorsChanged(propertyName);
}
I've got some tests around the scoping object that show that the expected/correct value of SuspendedAuthorizationScope.AuthorizationRulesAreSuspended is used as long as a lambda resolves in the scope of the using statement.
Are there any obvious flaws to this design? Is there anything in ASP.NET that I should be concerned with as far as threading goes?
There are two concerns that I see with your proposed approach:
One's failure to use using when creating SuspendedAuthorizationScope will lead to retaining open access beyond intended scope. In other words, an easy to make mistake will cause security hole (especially thinking in terms of future-proofing your code/design when a new hire starts digging in unknown code and misses this subtle case).
Attaching this magic flag to ThreadStatic now magnifies the previous bullet by having possibility of leaving open access to another page since the thread will be used to process another request after it's done with the current page, and its authorization flag has not been previously reset. So now the scope of authorization lingering longer than it should goes not just beyond missing call to .Dispose(), but actually can leak to another request / page and of completely different user.
That said, the approaches I've seen to solving this problem did involve essentially checking the authorization and marking a magic flag that allowed bypass later on, and then resetting it.
Suggestions:
1. To at least solve the worst variant (#2 above), can you move magic cookie to be a member of your base page class, and have it an instance field that is only valid to the scope of that page and not other instances?
2. To solve all cases, is it possible to use Functors or similar means that you'd pass to authorization function, that would then upon successful authorization will launch your Functor that runs all the logic and then guarantees cleanup? See pseudo code example below:
void myBizLogicFunction()
{
DoActionThatRequiresAuthorization1();
DoActionThatRequiresAuthorization2();
DoActionThatRequiresAuthorization3();
}
void AuthorizeAndRun(string memberName, AuthorizedAction authorizationAction, Func privilegedFunction)
{
if (IsAuthorized(memberName, authorizationAction))
{
try
{
AuthorizationRulesAreSuspended = true;
privilegedFunction();
}
finally
{
AuthorizationRulesAreSuspended = true;
}
}
}
With the above, I think it can be thread static as finally is guaranteed to run, and thus authorization cannot leak beyond call to privilegedFunction. I think this would work, though could use validation and validation by others...
If you have complete control over your code and don't care about hidden dependencies due to magic static value you approach will work. Note that you putting big burden on you/whoever supports your code to make sure there is never asynchronous processing inside your using block and each usage of magic value is wrapped with proper using block.
In general it is bad idea because:
Threads and requests are not tied one-to one so you can run into cases when you thread local object is changing state of some other request. This will even more likely to happen in you use ASP.Net MVC4+ with async handlers.
static values of any kind are code smell and you should try to avoid them.
Storing request related information should be done in HttpContext.Items or maybe Session (also session will last much longer and require more careful management of cleaning up state).
My concern would be about the potential delay between the time you leave your using block and the time it takes the garbage collector to get around to disposing of your object. You may be in a false "authorized" state longer than you intend to be.

Azure Cache - How to Determine if a Key is in cache?

Is there a way, using Azure Caching, to determine if an object having a specific key exists in cache, without actually returning the object itself?
I'm currently doing something like
public bool IsKeyInCache(string cacheKey)
{
DataCacheItem item = null;
CacheRetryPolicy.ExecuteAction(() =>
{
item = cache.GetCacheItem(cacheKey);
});
return item != null;
}
But, because the object in cache is very large and expensive to deserialize, performance is horrible.
I've dug through the MSDN documentation and don't see any alternative, but maybe I'm missing something.
My best idea so far is to add a small "marker" object to cache at the same time as my large object and check for existence of the "marker" object where deserialization is inexpensive. But this isn't a robust solution, as it's entirely possible for my large object to get purged from cache while the "marker" object remains.
I believe the API you're looking for is DataCache.Get(key):
windows azure caching - best practice for checking whether a key exist or not
http://msdn.microsoft.com/en-us/library/ff424908%28v=azure.10%29.aspx
But I still think you're best bet is to NOT "micro-manage" the cache, just query, and let Azure decide.
IMHO...

What are the dangers of using Session.SyncRoot for locking per session?

I have a race condition with the following code if two requests come in really close together in an ASP.NET MVC app:
var workload = org.Workloads.SingleOrDefault(p => ...conditions...);
if (workload == null) {
workload = org.CreateWorkload(id);
}
workload and org are EntityFramework objects. The call to CreateWorkload adds a row to a Workloads table in the database. (We really should enforce this with a UNIQUE constraint on the table, but I can't now that the table has some dirty data in it.) Subsequent calls to the Action method that contains this code throws an exception when SingleOrDefault encounters more than one row satisfying the conditions.
So to fix this, I want to lock these lines of code. I don't want it done per request, with static lock object because that slows the site down for every user. What I'd like to do is use Session.SyncRoot for locking. I.e.
Workload workload;
lock (Session.SyncRoot)
{
workload = org.Workloads.SingleOrDefault(p => ...conditions...);
if (workload == null) {
workload = org.CreateWorkload(id);
}
}
I'm not an ASP.NET expert, however, and there are some warning signs showing up in the docs and ReSharper, namely, that it can throw NotImplementedExceptions or be null. However, testing shows that this works just fine.
So, ASP.NET experts, what are the risks of using Session.SyncRoot for this? As an alternative, if Session.SyncRoot is "really risky", could I assign a lock object in the Session collection on Session start up to do the same thing?
The danger only exists if you use a custom session class that implements HttpSessionStateBase but doesn't override the SyncRoot property to do something other than throw a NotImplementedException. The HttpSessionStateWrapper class and the HttpSessionState class DO implement and override the SyncRoot method. So, as long as you're accessing the Session via the HttpSessionStateWrapper or HttpSessionState classes and not a custom class, this will work just fine.

Is this code thread-safe? How can I make it thread-safe?

I have a WCF service with a security class for getting some of the attributes of the calling user. However I'm quite bad when it comes to thread safety - to this point, I haven't needed to do much with it, and only have a rudimentary theoretical understanding of the problems of multi-threading.
Given the following function:
public class SecurityService
{
public static Guid GetCurrentUserID()
{
if (Thread.CurrentPrincipal is MyCustomPrincipal)
{
MyCustomIdentity identity = null;
MyCustomPrincipal principal = (MyCustomPrincipal)Thread.CurrentPrincipal;
if (principal != null)
{
identity = (MyCustomIdentity)principal.Identity;
}
if (identity != null)
{
return identity.UUID;
}
}
return Guid.Empty;
}
}
Is there any chance that something could go wrong in there if the method is being called at the same time from 2 different threads? In my nightmares I see terrible consequences if these methods go wrong, like someone accidentally getting someone else's data or suddenly becoming a system administrator. A colleague (who also he was not an expert, but he's better than me) thought it would probably be okay because there's not really any shared resources that are being accessed there.
Or this one, which will access the database - could this go awry?
public static User GetCurrentUser()
{
var uuid = GetCurrentUserID();
if (uuid != null)
{
var rUser = new UserRepository();
return rUser.GetByID(uuid);
}
return null;
}
There's a lot of discussion about the principals of threading, but I tend to fall down and get confused when it comes to actually applying it, and knowing when to apply it. Any help appreciated.
I can explain more about the context/purpose of these functions if it's not clear.
EDIT: The rUser.GetByID() function basically calls through to a repository that looks up the database using NHibernate. So I guess the database here is a "shared resource", but not really one that gets locked or modified for this operation... in which case I guess it's okay...?
From what I see, the first example only accesses thread-local storage and stack-based variables, while the second one only accesses stack-based variables.
Both should be thread-safe.
I can't tell if GetByID is thread safe or not. Look to see if it accesses any shared/static resources. If it does, it's not thread-safe without some additional code to protect those resources.
The code that you have above doesn't contain any code that changes global state, therefore you can be fairly sure that it won't be a problem being called by multiple simlutaneous threads. Security principal information is tied to each thread, so no problem there either.

Categories

Resources