GenericPrincipal error when logged in

GenericPrincipal error when logged in

Old forum URL: forums.lhotka.net/forums/t/285.aspx


poindexter12 posted on Tuesday, June 06, 2006

I am having an issue with the GenericPrincipal popping up when it should not.  Heres the scenario:

I log in like normal (using MyCustomPrincipal and MyCustomIdentity).  Authentication works and I set the Csla.ApplicationContext.User accoringly.  Everything is good.  As soon as I click on anything (actually as soon as another line of code executes), my Csla.ApplicationContext.User is now set to a System.Security.Principal.GenericPrincipal.  If I repeat the process, only this when I log in, I IMMEDIATELY log back out, and then log in again.  The issue goes away.  I have tried analyzing my Login() and Logout() functions but they are fine.  The kicker is, the code worked fine with Csla 2.0 but began behaving irregularly when I upgraded to Csla 2.0.1.  I have made some minor changes to the framework including implementing TcpChannel as well as a change to allow multiple portals in one application.  However, like I said this was working correctly in 2.0.  Any ideas?  Thanks in advance.

ajj3085 replied on Tuesday, June 06, 2006

Are you doing anything with threads?  (Including code that executes as part of a timer elasped event).

Andy

poindexter12 replied on Tuesday, June 06, 2006

I am doing something with a System.Windows.Forms.Timer but it has nothing to do with the scope of logging in.  It is merely for the displaying of the last action in the bottom bar for a few seconds.

poindexter12 replied on Tuesday, June 06, 2006

I have isolated the error outside of Csla.  Still, my issue torments me.  Does anybody have any ideas as to what would be causing this problem?  To be more specific, at some time after I log in and my first form is coming into focus, my Thread.CurrentPrincipal is being changed.  Please HELP!!!

ajj3085 replied on Wednesday, June 07, 2006

Is it ApplicationContext.User that is changing or Thread.CurrentPrincipal?

If its the latter, you'll need to set (on your application startup) the default principal for new threads.

See AppDomain.SetThreadPrincipal for more info.

HTH
Andy

poindexter12 replied on Wednesday, June 07, 2006

It definately is the Thread.CurrentPrincipal.  I am setting it.  I have made some further discoveries though.  It seems that what is actually happening is that the Thread.CurrentPrincipal is reverting back the the previous state.  When I call MyCustomPrincipal.Logout() (thus setting the Thread.CurrentPrincipal to MyCustomPrincipal.UnauthenticatedPrincipal) before starting my app, after logging in instead of changing to a GenericPrincipal it changes BACK to what it was before, MyCustomPrincipal.UnauthenticatedPrincipal.  Any ideas on how to solve this problem or even debug it so I can see when it is changing because it is definately NOT happening from me setting Csla.ApplicationContext.User.  Thanks.

ajj3085 replied on Wednesday, June 07, 2006

The method I mentioned probably needs to be called during your Logout procedure as well as your Login procedure.  It doesn't change the current thread's principal, it changes what the CurrentPrincipal will be set to for new threads.  For existing threads, it won't do anything, so before calling Logout I would tell your threads to shutdown somehow. 

HTH
Andy

ajj3085 replied on Wednesday, June 07, 2006

One more question..

Is there any reason you're looking at Thread.CurrentPrincipal instead of ApplicationContext.User?

andy

poindexter12 replied on Wednesday, June 07, 2006

From what I have seen, calling AppDomain.CurrentDomain.SetThreadPrincipal is designed to set the default principal, not the current principal.  However, I am calling this on start of my application with a empty MyCustomPrincipal which has now eliminated my casting error from the GenericPrincipal object.  However, I am still having the issue with reverting back to the original principal state (now a empty MyCustomPrincipal). 

As to your other question, the reason I am even looking at Thread.CurrentPrincipal is because ApplicationContext.User was returning that anyway.  I am just trying to find the soure of the problem, which seems at this point to have nothing to do with Csla.

Furthermore, I have been doing some research and the problem I am experiencing seems to be the exact problem that happens on an ASP.NET site when running Cassini, but that is just a guess.  Let me further explain the ONLY place my timer is running (also note that I have tried commenting this out to isolate the problem).  My timer runs like this:

The StatusBusy object that comes with the ProjectTracker solution I have modified.  It can be created as an instance or called via a static method.  In the end, both methods create an instace of "StatusBusy" and launch a timer to display a message "Im busy doing something" at the bottom of the screen in a status bar.  On timer tick, three seconds or so later, StatusBusy.Dispose() is called and the object is destroyed, unsubscribing timer events and setting the status message back to blank.

When removing that functionality totally, my problem still occurs.

ajj3085 replied on Wednesday, June 07, 2006

poindexter12:

From what I have seen, calling AppDomain.CurrentDomain.SetThreadPrincipal is designed to set the default principal, not the current principal.  However, I am calling this on start of my application with a empty MyCustomPrincipal which has now eliminated my casting error from the GenericPrincipal object.  However, I am still having the issue with reverting back to the original principal state (now a empty MyCustomPrincipal).

On logout, are you calling SetThreadPrincipal and giving it the GenericPrinpal?  If not, new threads will continue to use the custom principal.

poindexter12:
As to your other question, the reason I am even looking at Thread.CurrentPrincipal is because ApplicationContext.User was returning that anyway.  I am just trying to find the soure of the problem, which seems at this point to have nothing to do with Csla.

Oh, i see.  I haven't really studied that code yet in detail (very slowly working through the book). 

poindexter12:
Furthermore, I have been doing some research and the problem I am experiencing seems to be the exact problem that happens on an ASP.NET site when running Cassini, but that is just a guess.

I'm not familar with that problem; still haven't gotten into an Asp.Net 2.0 project yet.  I'll likely start tinkering with it home in my free time (so who knows when Wink [;)]).

poindexter12:
Let me further explain the ONLY place my timer is running (also note that I have tried commenting this out to isolate the problem).  My timer runs like this:

The StatusBusy object that comes with the ProjectTracker solution I have modified.  It can be created as an instance or called via a static method.  In the end, both methods create an instace of "StatusBusy" and launch a timer to display a message "Im busy doing something" at the bottom of the screen in a status bar.  On timer tick, three seconds or so later, StatusBusy.Dispose() is called and the object is destroyed, unsubscribing timer events and setting the status message back to blank.

When removing that functionality totally, my problem still occurs.

I'm not sure if follow (again, not that far in the book); are you removing the use of a timer at all?  If you remove your functionality but still use a timer, its likely the Timer's Elasped event is running from a ThreadPoolThread.  If that's the case, it may still use the 'default'.     You may have to dispose of and recreate the timer for it to use the new principal.. I'm not sure how the Timer works behind the scenes though.  I'm also not sure how SetThreadPrincipal affects ThreadPoolThreads, if this is where the timer is in fact getting its threads.
Andy

poindexter12 replied on Wednesday, June 07, 2006

I have completely removed the use of the timer for purposes of isolating the problem.  Also, from what I have seen and tried, AppDomain.CurrentDomain.SetThreadPrincipal can only be called ONCE, after that it throws an error.  It is designed, I think so anyway, to be called on the start of your program to change what your default principal will be.  In other words, I don't think the ability exists to call it after logout.

poindexter12 replied on Wednesday, June 07, 2006

FYI, the problem was that the first time I was logging in, the LogIn() function was being called in an event handler (MainForm_FormShown), which I am guessing is on a different thread that the main application.  This is why when I would log out and log back in, it would work fine.  Stupid threads...

ajj3085 replied on Wednesday, June 07, 2006

Hmm,

I'm not sure what else to do in this case.  I remembered I did come across this, and I solved it by always setting the CurrentPrincpal before running my business code.   That was easy though, since I'm always using WindowsPrincipal for the current user.

Could you stick the user in the ApplicationContext.GlobalContext and just pull it out and mantually assign it when you're in the other threads?

Andy

Copyright (c) Marimer LLC