I see where I was going wrong. I was running in the VS2010 debugger, and it stopped at the throw line. If I run Console01.exe from the bin\Debug directory, it works.
I added two more Console.WriteLine statements, and it does get back to the Client, as shown.
Thread principal before login: Non-Windows Login About to Throw on Server... In Client Catch LoginException: 'johnx' is not a user name in the 'domain' domain. Press ENTER to exit...
I was expecting the Debuger to find the Catch statement in the Client. Sorry. I assume you were running the exe directory?
I tried version 6.1.0 and 6.1.1. However, I don't think it has anything to do with the version. I do hope though that I'm not misunderstanding your question.
To clarify, you want a LoginException thrown on the server and caught on the client. In my code sample, I have the following:
CLIENT
try {
// Login will null credentials. The LoginManager will decide what to do ...
Hello Denis, Thanks for code sample. Unfortunately it runs with same issue on my laptop - throws in LoginManager on the Server. I've upgraded to 6.1.1 from 6.1.0. No change.
What version of DF did you compile and run against? Please attach copy of your DebugLog after a failed login.
Hello DenisK, Thank you for your time in search back to my question.
I'm sorry, but I do not find,
throw new LoginException(LoginExceptionType.InvalidUserName, credential.Domain, credential.UserName);
returning to the Client, as this DebugLog file below shows. The application stops dead at the throw statement.
I guess that calling Login is early in your library's initialisation, and the method for returning to the Client is not available.
thanks John
<?xml version="1.0"?><?xml-stylesheet href="DebugLog.xsl" type="text/xsl"?> <log> <entry id="14" timestamp="2011-06-23T19:36:20" username="" source="IdeaBlade.Core.TraceFileXmlLogger:GetLogHeader">------------ Log Created ------------</entry> <entry id="0" timestamp="2011-06-23T19:36:15" username="" source="Console01.Program:DoIt">TraceFns: Program Starting...</entry> <entry id="1" timestamp="2011-06-23T19:36:15" username="" source="Console01.Program:DoIt">DebugFns: Program Starting...</entry> <entry id="2" timestamp="2011-06-23T19:36:15" username="" source="IdeaBlade.Core.IdeaBladeConfig:Initialize">Initializing configuration ...</entry> <entry id="3" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.Composition.PartsCatalog:LoadCatalog">MEF assembly probing started: 23/06/2011 19:36:17. If this takes a long time, use IdeaBlade.Core.Composition.CompositionHost to specify/restrict which assemblies to probe.</entry> <entry id="4" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.Composition.PartsCatalog:LoadCatalog">Assembly 'Console01, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' added to PartsCatalog</entry> <entry id="5" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.Composition.PartsCatalog:LoadCatalog">Error loading assembly 'C:\VSProjects\VS2010\DevForce\Console_SecurityWindowsAuthentication\080_Secure\Console_SecurityWindowsAuthentication-2TierNoServer\CodeCS\Console01\bin\Debug\Console01.exe.config' for PartsCatalog: Error with file Console01.exe.config.</entry> <entry id="6" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.Composition.PartsCatalog:LoadCatalog">MEF assembly probing completed: 23/06/2011 19:36:17</entry> <entry id="7" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.Composition.CompositionHost:.ctor">Probe Assemblies: Console01, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null :: SimpleNorthwindModel.Desktop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null :: WPFTraceViewer, Version=6.1.0.0, Culture=neutral, PublicKeyToken=287b5094865421c0 If this list is unnecessarily large, use CompositionHost.SearchPatterns to modify the search critieria for probed assemblies. If this list does not contain the assembly(ies) holding your a) domain model, b) custom interface implementations, and c) POCO/known types then your application may not work correctly. Ensure that these assemblies are available in the exe/bin folder, and if using CompositionHost.SearchPatterns that the patterns are set appropriately.</entry> <entry id="8" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.IdeaBladeConfig:InitializationStatusCallback">IdeaBlade License: 'EnterpriseUniv, Express', KeyDate: 15/04/2010, AllowedSessions: 10000. Found on Assembly: 'SimpleNorthwindModel.Desktop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'</entry> <entry id="9" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.Configuration.ServerSettingsElement:ConstrainSettingsBasedOnLicenseCore">The configured SupportedClientApplicationType is Both</entry> <entry id="10" timestamp="2011-06-23T19:36:17" username="" source="IdeaBlade.Core.Configuration.ServerSettingsElement:ConstrainSettingsBasedOnLicenseCore">Could not find a valid license to enable session-agnostic load balancing.</entry> <entry id="11" timestamp="2011-06-23T19:36:20" username="" source="IdeaBlade.Core.Configuration.ServerSettingsElement:ConstrainSettingsBasedOnLicenseCore">Could not find a valid license to enable session-agnostic load balancing.</entry> </log>
I'd much prefer to have LoginExceptionType.InvalidUserName returned to the Client. Please can you suggest a way?
To do this, you can throw a LoginException back to the client.
throw new LoginException(LoginExceptionType.InvalidUserName, credential.Domain, credential.UserName);
I see that you commented that part of the code out and you create a GenericIdentity instead with IsAuthenticated = false. A login and authentication are 2 different processes. A user can successfully login but not authenticated. To disallow login, a LoginException needs to be thrown.
Alternatively, can you support:-
var loginResult = mgr.Login((ILoginCredential)cred);
var isLoggedIn = mgr.IsLoggedIn;
as false, when the login fails. So that one can test in the Client, and not have an exception.
Currently, as I've noted above, to indicate a failed login, one has to throw a LoginException. If you have a convincing use case for this, I might be able to discuss this with a senior engineer and add it to the feature request list.
Hi, Using your example Console_SecurityWindowsAuthentication, which I have arranged to be 2-tier, I am adding code to support non-Windows Generic Identity Authorization.
In your code example of IEntityLoginManager you have a LoginException being generated on the Server side (which is of course in 2-tier also running on the client), if the login fails.
On the otherhand, if the GenericIdenity.IsAuthenticated
is false, the login as seen by the Client still succeeds.
Also, EntityServerQueryInterceptor is probed for after the login is completed.
The only way I can find of returning a failed login back to the Client is to return a null UserBase. This causes a EntityServerException
of "Session Bundle is invalid". Which matches your code example. Only in the Catch blocks is EntityManager.IsLoggedIn
false.
I'd much prefer to have LoginExceptionType.InvalidUserName returned to the Client. Please can you suggest a way?
Alternatively, can you support:-
var loginResult = mgr.Login((ILoginCredential)cred);
var isLoggedIn = mgr.IsLoggedIn;
as false, when the login fails. So that one can test in the Client, and not have an exception.
//Client void DoIt()
{
NorthwindManager mgr = newNorthwindManager();
//IdeaBlade.Core.IdeaBladeConfig.ConfigFileAssembly = Assembly.GetExecutingAssembly();var configInstance = IdeaBlade.Core.IdeaBladeConfig.Instance;
configInstance.ObjectServer.ClientSettings.IsDistributed = false;
configInstance.ObjectServer.ServerSettings.AllowAnonymousLogin = false;
configInstance.ObjectServer.ServerSettings.LoginManagerRequired = true;
configInstance.Logging.ShouldLogSqlQueries = true;
configInstance.Logging.LogFile = "MyLogFile.xml"; //not working.
Console.WriteLine("Thread principal before login: {0}", System.Threading.Thread.CurrentPrincipal.Identity.Name);
bool isLoggedIn = false;
bool loginResult = false;
try
{
// Login will null credentials. The LoginManager will decide what to do ...LoginCredential cred = newLoginCredential("john", "password", "domain");
//loginResult = mgr.Login((ILoginCredential)null);
loginResult = mgr.Login((ILoginCredential)cred);
isLoggedIn = mgr.IsLoggedIn;
Console.WriteLine("Thread principal after login: {0}", System.Threading.Thread.CurrentPrincipal.Identity.Name);
}
catch (LoginException le)
{
Console.WriteLine("LoginException: " + le.Message);
isLoggedIn = mgr.IsLoggedIn;
Console.WriteLine("Press ENTER to exit...");
Console.ReadLine();
return;
}
catch (EntityServerException ese)
{
Console.WriteLine("EntityServerException Login failed: " + ese.Message);
isLoggedIn = mgr.IsLoggedIn;
Console.WriteLine("Press ENTER to exit...");
Console.ReadLine();
return;
}
catch (Exception ex)
{
bool isLogged = mgr.IsLoggedIn;
Console.WriteLine(ex.Message);
return;
}
// etc.... }
//Server publicIPrincipal Login(ILoginCredential credential, EntityManager entityManager)
{
if (credential == null)
{
// if running n-tier the user's Windows credentials will be passed and available on the thread:var principal = System.Threading.Thread.CurrentPrincipal;
if (principal.Identity.IsAuthenticated)
{
Logger.WriteMsg(string.Format("principal is {0}", principal.Identity.Name));
// Note that we can't return the WindowsPrincipal/WindowsIdentity back to the client, so// create a new one, here we use the DevForce UserBase class, but you can create your own too. return CreateUser(principal);
}
else
{
// This is here for 2-tier testing, since you'll probably want to throw an error or do// some custom logic in n-tier. When not running n-tier, the thread principal has not been set // but you can obtain the Windows Identity and use that.var wi = WindowsIdentity.GetCurrent();
Logger.WriteMsg(string.Format("wi is {0}", wi.Name));
WindowsPrincipal wp = newWindowsPrincipal(wi);
return CreateUser(wp);
}
}
else
{
Logger.WriteMsg("Non-Windows Login");
GenericIdentity gi = null;
if (credential.UserName.Equals("john")) //change to somthing else to force failure
{
gi = newGenericIdentity(credential.UserName, "MyAuthoType");
}
else
{ //This is the way of getting IsAuthenticated set to false
gi = newGenericIdentity("", "MyAuthoType");
//This will throw in EntityServer// throw new LoginException(LoginExceptionType.InvalidUserName, credential.Domain, credential.UserName);
}
GenericPrincipal gp = newGenericPrincipal(gi, null);
Logger.WriteMsg("Non-Windows Login Completed.");
return CreateUser(gp);
}
thrownewNotImplementedException("Some Login Error");
}
privateUserBase CreateUser(IPrincipal currentUser)
{
// The UserBase and UserIdentity classes are custom IPrincipal/IIdentity implementations// within DevForce. UserIdentity identity = newUserIdentity(currentUser.Identity.Name, currentUser.Identity.AuthenticationType, currentUser.Identity.IsAuthenticated);
bool isInRole = currentUser.IsInRole("");
var isAuth = currentUser.Identity.IsAuthenticated;
// You can determine what roles to set, if any.string[] roles = newstring[] { };
if (isAuth)
{
Logger.WriteMsg("UserBase created.");
returnnewUserBase(identity, roles);
}
//Will result in an EntityServerException in the ClientLogger.WriteMsg("Null UserBase returned.");
returnnull;
}
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum