logout reset after event finishes

logout reset after event finishes

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


odie posted on Monday, September 10, 2007

I am working on an application that monitors when a memory card is inserted or removed from a card reader. using the following code:

Private Sub StartDriveChange()
mMediaConnectWatcher =
New Management.ManagementEventWatcher("root\cimv2", _
"Select * From __InstanceOperationEvent Within 1 Where " _
&
"TargetInstance isa 'Win32_LogicalDisk' and TargetInstance.DriveType = 2")

mMediaConnectWatcher.Start()

AddHandler mMediaConnectWatcher.EventArrived, AddressOf mCardReader.CardInsertRemoveEvent
End Sub

When the CarInsertRemovedEvent fires I run the logout method on my PHPrincipal class which does log the user out, but when CardInsertRemoveEvent finishes csal.ApplicationContext.User is restored to what it was before I logged out.

The logout method is:

Private Sub Logout()

If Me.InvokeRequired Then

Me.Invoke(New MethodInvoker(AddressOf Logout))

Else

Common.Security.PHPrincipal.Logout()

mLogout = True

End If
End Sub

Any ideas how to keep the users logged outwhen the event finishes? I currently use the mLogout = true and check it later on to see if the logout function has been run but this is just a hack to get around the problem.

 

RockfordLhotka replied on Monday, September 10, 2007

You may want to use the threads window in the debugger to make sure you really are running the logout code on the UI thread.

odie replied on Monday, September 10, 2007

Doesn't the me.InvokeRequired take care of that in the logout method?

RockfordLhotka replied on Monday, September 10, 2007

You would think so, yes. But it is easy enough to put a breakpoint in the code and then use the threads window to make sure you are on the thread you think you should be using.

odie replied on Monday, September 10, 2007

All login/logout calls are taking place on the same thread ID. I even checked which thread the whole application is starting under when the form first loads and it is the same.

For some reason csla.applicationcontext.user it is being reset to before the logout is called when the cardInsertRemovedEvent method finishes running.

RockfordLhotka replied on Monday, September 10, 2007

Interesting.

Csla.ApplicationContext.User (when not running in ASP.NET) gets/sets the principal value at System.Threading.Thread.CurrentPrincipal.

That value is owned by .NET, and there are some things that can affect it. Both WPF and VB will alter this value based on some policy settings, and you can specify that it default to a WindowsPrincipal in any environment by calling a method on the AppDomain.

However, to my knowledge, only WPF alters the value during runtime - meaning after application startup. The AppDomain setting only affects startup, and that's true for the VB policy as well (they rely on the core AppDomain value and then add some extra functionality - but it all happens at startup).

I assume you aren't using WPF?

So that should eliminate all the automatic principal changing that I'm aware of - leaving only your code as a culprit Wink [;)]

So what I'd recommend at this point, is putting a breakpoint in your login and logout methods. You should see the logout occur - which should set the value. Then something must be setting the System.Threading.Thread.CurrentPrincipal value back, which you'd think would be the login method?

odie replied on Monday, September 10, 2007

When I check the value right after the logout csla.applicationcontext.user is logged out as expected. Even checking this value with a break point on the End Sub of the CardInsertRemovedEvent shows it logged out. as soon as you step past the End Sub the value is reset back to what it was before I logged out, no other code of mine gets run until the user presses a button on the form.

What you suggest I have already done many times and the login is not getting called. And I am not using WPF.

RockfordLhotka replied on Monday, September 10, 2007

Then I have no idea, sorry.

 

If you are on the correct thread, and you’ve set the value, then something is setting the value back.

 

If you are in WPF I’ve seen the runtime change the value back.

 

If you are in VB it can change the value, but I think that only happens on app startup.

 

Beyond that, I just don’t have any idea.

 

Rocky

 

From: odie [mailto:cslanet@lhotka.net]
Sent: Monday, September 10, 2007 3:04 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] logout reset after event finishes

 

When I check the value right after the logout csla.applicationcontext.user is logged out as expected. Even checking this value with a break point on the End Sub of the CardInsertRemovedEvent shows it logged out. as soon as you step past the End Sub the value is reset back to what it was before I logged out, no other code of mine gets run until the user presses a button on the form.

What you suggest I have already done many times and the login is not getting called.



odie replied on Monday, September 10, 2007

I'll put together a small project with the approprate code that reproduced the problem for you to have a look at when you have time and see if you can find out what I am missing.

ward0093 replied on Wednesday, October 10, 2007

Hi Odie... did you ever figure this out???  I just ran into it on my dev machine (in debug mode).  Tried all your tests and something is setting the user object back to it's original value after the function finishes up.  Really Weird!

and nothing is calling the Login Method at all...

I have not tested in production yet (or not with this latest release) but something is happening (the currentIdentity is getting set back) and I can not track it down.

Any Thoughts?

ward0093

RockfordLhotka replied on Wednesday, October 10, 2007

I had a discussion with Kathleen Dollard, as she ran into something similar.

 

In her case the assemblies were VB assemblies, and she’d referenced one EXE from another EXE (using the first one more like a DLL).

 

VB’s My namespace includes some functionality to simplify the use of principal objects in an EXE. Interestingly enough, it turns out that calling one EXE from another EXE (like you would a DLL) also triggers this functionality and resets the principal based on the security policy set in that referenced EXE project.

 

Maybe a clue?

 

As I’ve said in previous posts – WPF will do this to you as well, in VB or C#. And WCF will do it under specific circumstances as I discuss in Using CSLA .NET 3.0.

 

Rocky

 

 

From: ward0093 [mailto:cslanet@lhotka.net]
Sent: Wednesday, October 10, 2007 2:07 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: logout reset after event finishes

 

Hi Odie... did you ever figure this out???  I just ran into it on my dev machine (in debug mode).  Tried all your tests and something is setting the user object back to it's original value after the function finishes up.  Really Weird!

and nothing is calling the Login Method at all...

I have not tested in production yet (or not with this latest release) but something is happening (the currentIdentity is getting set back) and I can not track it down.

Any Thoughts?

ward0093



ward0093 replied on Wednesday, October 10, 2007

Well... I am not calling external EXE but i do use multiple threads frequently.  Could that be causing it?

Is there a way to fix it?

ward0093

RockfordLhotka replied on Wednesday, October 10, 2007

.NET keeps the principal object attached to a thread. So if you switch threads, you are responsible for ensuring that each of those threads has the right principal.

 

When you set the principal (using Csla.ApplicationContext.User, HttpContext.Current.User, System.Threading.Thread.CurrentPrincipal or My.User) the principal is only set for the current thread. That’s how .NET works. Everything else (with multiple threads) is entirely up to you.

 

Rocky

ward0093 replied on Wednesday, October 10, 2007

Is there a chance that the main thread (the thread I am logged out of recently) is getting set back by another, background thread?  I am logging out inside a FormShown event too!  That could be it as well do you think?

odie replied on Wednesday, October 10, 2007

I sort of used a hack. I set a variable inside the thread event indicating that the user should be logged out and then force a log out the next time a user performs any other action, outside any threads. This is not a big deal in my application as there are only 4 things a user can actually do.

Not the nicest solution but it does work.

RockfordLhotka replied on Wednesday, October 10, 2007

I think I’m doing something similar in PTWpf :)

 

Because WPF resets the principal (when it shouldn’t imo), I store the current principal in a Shared/static field (thus making it available at the AppDomain level). The data portal now has a new (to version 3.0) init event that I then handle in the same code module where that Shared/static field is declared (the app’s main form in my case). In that event handler I see if the current principal is the same as my _principal field (using ReferenceEquals()) and if they are not the same, I set the thread’s principal to _principal.

 

The _principal field is changed only in my LoginOut() method, so it reflects the correct value according to my application.

 

This technique not only addresses the WPF need, but would resolve most multi-threading scenarios as well – at least from the data portal perspective.

 

Rocky

 

From: odie [mailto:cslanet@lhotka.net]
Sent: Wednesday, October 10, 2007 2:32 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: RE: logout reset after event finishes

 

I sort of used a hack. I set a variable inside the thread event indicating that the user should be logged out and then force a log out the next time a user performs any other action, outside any threads. This is not a big deal in my application as there are only 4 things a user can actually do.

Not the nicest solution but it does work.



ward0093 replied on Wednesday, November 07, 2007

Hey rocky,

I was using this thread just now: http://forums.lhotka.net/forums/thread/11358.aspx

but realized we discussed this already... above you mention transferring the principal to the server but i am still trying to figure out why the principal object gets reset on the Main UI thread after a successful login?

ward0093

ward0093 replied on Wednesday, November 07, 2007

Something is really strange with the Multi-Threading and the current principal object.

I write out to the EventLog the user credentials (UserID, IsAuth., etc) both inside the "DoWork" event and in the "ProgressChanged" event (part of the Background Worker object).  The ProgressChanged method is on the UI thread and confirmed it with the ProcessID... but shows that the User is not set even after we successfully log on.

However, when we check the User Credentials in other places in the program on the UI thread, the user shows up and everything is fine?!?!?!

this there some sort of Refresh issue going on with the "ProgressChanged" Method that we fire from within the background worker component background thread?

very strange that is does not pull the current User from the CSLA.ApplicationContext module for the main UI thread that the "ProgressChanged" method is running on?

ward0093

P.S.  I am still on CSLA V2.1.2

RockfordLhotka replied on Wednesday, November 07, 2007

I don't know. It sure sounds like the BackgroundWorker may be "helping" you to manage the principal somehow...

Not to be too flippant, but I look forward to hearing what you find as you research this Smile [:)]

Is this something you can isolate into a very small demo that illustrates the problem? That might help debug the issue. Just the process of creating such an isolated demo might help reveal the issue.

ward0093 replied on Thursday, November 08, 2007

Hey Rocky... I will see what I can do to create a small app and duplicate it... but one thing is for sure... in my dev environment, in debug mode... the "ProgressChanged" method on the UI Thread is not updating the User Object (the Principal object) and that has to be a bug! (or I am missing something)

I will keep you posted when I get the app done... also I am going to leave my EventLog writeouts in the app and release it to production and see if that happens in a compiled format.

ward0093

Copyright (c) Marimer LLC