Loading UserPermissionCache with only 1 user's authorizations

Jun 11, 2009 at 3:24 PM
Edited Jun 11, 2009 at 3:28 PM

Hi Andrea,

In reference to the NetSqlAzMan documentation:

NetSqlAzMan.Cache.UserPermissionCache userPermissionCache = new NetSqlAzMan.Cache.UserPermissionCache(storage, "My Store", "My Application", IAzManDBUser , true, true);

If your application is a Web Application you can put UserPermissionCache instance into a Session variable or in the ASP.NET Cache to cache authorizations for all the session time. This step avoid UserPermissionCache rebuilding.

My assumption would be that the IAzManDBUser argument supplied in the ctor UserPermissionCache(IAzManStorage, String, String, IAzManDBUser ...

would limit the returned Items and related Authorizations to those associated dbUser. That way only that user's authorizations could be cached in the user's web application session. However, it appears that when inspecting the UserPermissionCache object after loading that it actually contains all Application Items  and all user authorizations to those items. Loading all items and authorizations for the entire application would make for a very heavy object.

Is there a way to limit the Items and associated authorizations loaded into the UserPermissionCache to just a single user? This is what I believed was the purpose of the IAzManDBUser argument in the UserPermissionCache ctor. Am I missing something important? Using the wrong object?

Regards, Bill

Coordinator
Jun 11, 2009 at 3:38 PM
Hi,
your assumptions are correct.

The class UserPermissionCache keeps in cache the complete set of all the permissions but for a single user, so each user must keep the own instance of the class UserPermissionCache in a Session variable or in the asp.net cache but hanging to the name of the cache key the Session.SessionID own.
As an alternative (and much more performance with the latest NetSqlAzMan version) you can store a single instance of the class StorageCache for all users (in one variable or on the Application Cache) which preserves the permissions for all users for one or more NetSqlAzMan Applications.
The StorageCache class can even keep the entire permissions set for the entire Storage.
If you need to limit the set to a single application, simply pass the StoreNameFilter and ApplicationNameFilter parameters to the StorageCache.buildStorageCache (..., ...) method.
Regards,
Andrea.

Jun 11, 2009 at 5:00 PM
Edited Jun 11, 2009 at 5:04 PM

Hi Andrea,

Thanks for the additional information however, there will likely be way too many users and authorizations to make populating a single application level authorization object practical.  Per user and session will likely be ideal for my situation.

For the UserPermissionCache, I'm using version: 3.5.4.2. When I create the cache using  the code below and then drill into the object in debug mode I see all  the application's Items definitions and all associated Item authorizations across the entire application store for all users. Not just the authorizations for the supplied user in the argument.

string userName = myuser@xx.com;

IAzManDBUser dbUser = storage.GetDBUser(userName);
NetSqlAzMan.Cache.UserPermissionCache userPermissionCache = new NetSqlAzMan.Cache.UserPermissionCache(storage, storeName, applicationName, dbUser, false, false);

For example, then I drill into userPermissionCache.Items[].Value.Authorizations[]. I see all users authorizations, not just myuser@xx.com's authorizations. So every authorization, regardless of user assignement has been loaded. I see there's now a version 3.5.4.3. Is there a bug fix or stored procedure update to correct this issue?  Am I simply coding something incorrectly?

Regards, Bill

 

 

 

 

 

Coordinator
Jun 11, 2009 at 9:38 PM
Hi Bill,
If to the StorageCache class, starting from the 3.5.4.2 release, are passed the StoreNameFilter and ApplicationNameFilter parameters to the BuildStorageCache(...,...) method It does not select all the permissions and all items ... but only those relating to the filtered application .
There is also the "AuthorizedItem[] GetAuthorizedItems(...)" method that returns you only the authorized Items (including attributes) that you can safely store into the User Session.
In summary:
1) In the ASP.NET Session_Start creates an instance of the StorageCache object by filtering the only application that involves and invokes the BuildStorageCache(StoreNameFilter, ApplicationNameFilter) method.
2) Invokes the GetAuthorizedItems method (giving the Windows/DB User identity), and retains in Session the resulting array.
3) At run-time check cached array to determine if the user is authorized or not.
This is the pattern that I recommend using both for web applications and Smart Client apps.
Also look at the charts in the NetSqlAzMan homepage (I've updated them) and understand that the StorageCache performance (for most users) are much higher (and better then UserPermissionCache multiplied to the number of users).

Please, Let me know.
Kind Regards,
Andrea.
Jun 12, 2009 at 12:16 PM
Edited Jun 12, 2009 at 12:17 PM

Hi Andrea,

Thanks very much for the detailed information and the very prompt replies.

I appreciate that the loading of StorageCache compared to UserPermission is overall faster. However, I'd assume that in environments where there are a very large number of users (say 50,000 users and 100s of thousands of associated authorizations) loading all of the applications's authorizations on a per user session initiation basis for the purpose of sorting out only those required for one user wouldn't be ideal; especially from a server memory usage standpoint. Further, attempting to use a global Application cache would typically not be a viable option because a user's authorizations can be changed between that user's sessions and so to have viable solution a user must retrieve the latest set of their authorizations at the time when they initiate a session.

I guess I would only say that testing will need to be performed to assess the memory impacts of loading the entire application's authorizations per session. Based on the constraints and issues listed above, I would assume that the only fallback position would be to simply retrieve that  user's authorization directly (no caching) through the CheckAccessHelper class?

BTW. I don't find a GetAuthorizedItems method in the 3.5.4.2 docs. Assume this is SqlAzManItem.GetAuthorizationsOfMember? Gets the authorizations by SID.

Regards, Bill

Coordinator
Jun 12, 2009 at 9:30 PM

Hi Bill,

The StorageCache.GetAuthorizedItems() method is available only from release 3.5.4.3 or later.

The result of this method would advance what you should keep into the Session data, such data are not the set of all authorizations for an application but only the set of Items for which that user is specifically authorized.

You should make tests of performance and memory consumption.

You will see that the solution I’m proposing to you is quite affordable.

Regards,

Andrea.

__________________________________
Andrea Ferendeles
NetSqlAzMan - Project Coordinator

http://netsqlazman.codeplex.com

Jun 30, 2009 at 2:49 PM
Edited Jun 30, 2009 at 5:38 PM

Hi Andrea,

Using version 3.6.0.1,  for example:

IAzManDBUser

dbUser = storage.GetDBUser(userName);

StorageCache sc = new StorageCache(cs);

sc.BuildStorageCache(

"MyStore", "MyApp");

AuthorizedItem[] userAuthorizedItems = sc.GetAuthorizedItems("MyStore", "MyApp", dbUser.CustomSid.StringValue, DateTime.Now, null);

If I'm calling this correctly, it appears that the array produced by GetAuthorizedItems contains Authorized Items even when the user supplied in parameter DBUserSSid does not have authorizations defined for that Item.

In addition, my application calls for the user being assigned multiple authorizations for same Item.  This means that a multiple Authorizations will be associated to a particular user and Item definition. The Console application definetely allows multiple user Authorizations per Item. As a result, I need to be able to query for all Authorization objects associated to any Items that exist for a user. During the user's Session I will allow the user to invoke a set of Authorizations based on a login context that they can select.

Also, the BuildStorageCache method does not allow for filtering of application authorizations per user as the GetAuthorizedItems method argauments suggest. Not supplyng a user argument will force the retrieval of all the application's authorizations across all users. Is there a consise and efficient way to load the StorageCache (or some other cache) per user authorizations?

Can the StorageCache but loaded per User Authorizations?

 

Regards, Bill

Coordinator
Jun 30, 2009 at 8:10 PM

Hi,

What do you mean exactly when you say “it appears that the array produced by GetAuthorizedItems contains Authorized Items even when the user supplied in parameter DBUserSSid does not have authorizations defined for that Item” ? Please give me an example.

For the other question …

When to a user you assign multiple authorizations on the same Item … the method GetAuthorizedItems() … returns the merged authorizations for that particular item (but with inside all Attributes).

Which are your needs ?

Let me know.

Regards,

Andrea.

__________________________________
Andrea Ferendeles
NetSqlAzMan - Project Coordinator

http://netsqlazman.codeplex.com

Jul 1, 2009 at 2:14 PM
Edited Jul 1, 2009 at 2:41 PM

Hi Andrea,

What do you mean exactly when you say “it appears that the array produced by GetAuthorizedItems contains Authorized Items even when the user supplied in parameter DBUserSSid does not have authorizations defined for that Item” ? Please give me an example.

Example: from the Console application

There are two roles defined in console's Item Definitions. Role1 and Role2.

There is a DBUser, dbUser that is supplied in the call to the GetAuthorizationItems method.

There are no/zero Authorizations defined for dbUser for Item Definitions: Role1 or Role2.

After the GetAuthorizationItems method call using dbUser as an argument, my expectation, based purely on method naming,  would be that the userAuthorizedItems array would contain zero elements due to the fact that dbUser does not have any Authorizations defined for either Role1 or Role2. However, there are two elements returned in userAuthorizedItems. One for Role1 and a second for Role2.

AuthorizedItem[] userAuthorizedItems = sc.GetAuthorizedItems("MyStore", "MyApp", dbUser.CustomSid.StringValue, DateTime.Now, null);

 

When to a user you assign multiple authorizations on the same Item … the method GetAuthorizedItems() … returns the merged authorizations for that particular item (but with inside all Attributes).

Which are your needs ? My application needs to maintain multiple sets of Item Authorizations.and access checks against the same Item Definitions. Since the access checks are against an ItemName key the check will not be unique. So, I might have to look at dynamically creating and revoking authorizations for the user against Item Definitions so that the user's access checks are against a unique set of Item Authorizations.

Coordinator
Jul 1, 2009 at 9:06 PM

Hi,

the AuthorizedItem class has these properties:

    public class AuthorizedItem

    {

        public string Name { get; set; }

        public ItemType Type { get; set; }

        public AuthorizationType Authorization { get; set; }

        public List<KeyValuePair<string, string>> Attributes { get; set; }

    }

So, for each Item (Name) you have to check related AuthorizationType field to get User Authorizations.

If there are no/zero Authorizations defined for dbUser for Item Definitions Role1 or Role2 ... you should have Neutral into the AuthorizationType property.

This feature is by design.

If your need is to create Authorizations dynamically ... WCFC cache service is not enough, you should use SqlAzManStorage class and all DOM Classes (referencing NetSqlAzMan.dll assembly)

Regards,

Andrea.

__________________________________
Andrea Ferendeles
NetSqlAzMan - Project Coordinator

http://netsqlazman.codeplex.com