Monday, August 22, 2011

LOGIN PATTERN USING MVVM AND PRISM IN COMBINATION WITH MAPSERVICES PART V

Introduction


Before tackling more complex functionality as web editing and “GeoProcessing”, we will introduce a login pattern for use with ArcGis Silverlight API.
When using the Silverlight API of ESRI with maps, having a consistent display with a login screen on a single web page can be painful. As long as the user has not been authenticated you can not display the map content. However due to the asynchronous operation of the map control, once you set the layer contents, the map becomes displayed. In the solution outlined hereafter we will respect the asynchronous character of Silverlight.
In PRISM you can create a dependencies of modules. The idea is to create a login module that will be depended from for all other modules.  

Authentication Framework


The authentication framework consists of two components:
  • Authentication module.
  • Authentication service.
The authentication module will handle all the input related to the login procedure. The module will use the authentication interface to save and mark the successful login.
The authentication service is the engine of the login procedure. The interface is responsible for the authentication and as service will also provide functionality to other modules when information is needed about function authorizations for the user logged in.
In case no authentication is required, you can use a dummy module that sets the authentication to true.  Doing this, you can later, by simple modifying the module catalog creating a login procedure without modifying your code.
Another situation is when the application runs in a trusted network environment. In this case you can use the user credentials as in an authentication module. This can be done through a WCF service that retrieves the user credentials through the instruction:
WindowsIdentity winIdent = (WindowsIdentity)HttpContext.Current.User.Identity;
Next we will treat in more detail the case of doing authentication through a login form.

Authentication Module


The authentication Module will consists of the visual aspects of the login procedure. To restrict the user interface, the login view consists of a ChildWindow initiated from the authentication module class.

The authentication module is responsible for sending a message to other modules of the successful login of a user. In case of not successful the startup op de Silverlight application is aborted. By using the HTTPRequest you could close the web page.

The login view consists of a username and password as input, a textbox that contains error messages and buttons to login or cancel the login process.

 


To close the ChildWindow, we must put code behind the two buttons. For the login button this means:

private void OKButton_Click(object sender, RoutedEventArgs e){
 if (authenticationViewModel.LogonCheck())
  this.DialogResult = true;
}


The window is created in the module class.

public void Initialize()
{
  logonEvent = 

   eventAggregator.GetEvent<CompositePresentationEvent<LogonData>>();
  ChildWindow childView = 

   container.GetExportedValue<AuthenticationChild>();
   childView.Closed += ChildView_Closed;
   childView.Show();
}


Control is handed back to the module class as soon as the login view is closed. To signal the success of the login, the module uses the EventAggregator service to publish a successful login. The modules that depend on the login process can then take action to complete there process. This is the case with the map module, which will wait to initialize the layer property until the login has been completed successful.

private void ChildView_Closed(object sender, EventArgs e)
{
  if (authentication.IsLoggedOn())
  {
   LogonData logonData = new LogonData() { LoggedOn = true };
   logonEvent.Publish(logonData);
  }
}


On the other module site (map module) you need to handle the successful login event by subscribing to the event:


if (eventAggregator != null)
  eventAggregator.GetEvent<CompositePresentationEvent<LogonData>> ().Subscribe(OnLogonChanged);

public void OnLogonChanged(LogonData logonData)
{
  configuration.SetFinishedEvent(new EventHandler

  (ConfigurationInitialised));
  configuration.GetConfiguration();
}


This was initially done in the module constructor when no login was required.

Authentication Service


This must be the engine behind the authentication process. By creating an authentication service, every module has access to information proper at the user logged in. As with other services, the functionality is exposed by means of an interface that was injected in the different module classes or view models that need authentication data. Typical information that will we maintained by this service is:

  • UserName and user detail information (full name, email, …).
  • Groups belonging to.
  • User credentials (Create, Read, Update and Delete for certain data).


The bootstrapper creates the authentication service and makes it available through the container:

private Authentication authentication = new Authentication();

this.Container.ComposeExportedValue<IAuthentication>(this.authentication);


The interface IAuthentication could be similar than the one showed below, and should be created in a common Silverlight project:

public interface IAuthentication {
  Boolean IsLoggedOn();
  string UserName();
  Boolean IsActionAllowed(string operation);
  Boolean IsActionAllowed(CRUD crud, string table);
  Boolean LogOn(string username, string password);
}
Data concerning the user logged in, are maintained in the authentication class and make accessible through the authentication interface:

private string userName;
private bool loggedOn = false;

public bool IsLoggedOn()
{
  return loggedOn;
}

public bool LogOn(string username, string password)
{
  boolean logOnOK = false;
…             

  // Validate through web service
  return logOnOK;
}

public string UserName()
{
  return userName;
}


 
By using dependency injection, view model and other classes have access to authorization data. Typical in the Authentication class, the LogOn method will access a web service for doing the authentication of the user. Because this is an asynchronous process, callback functionality must be foreseen to let the user wait until validation has been completed. This is a similar pattern we used a couple of times in the Gis operations.

In case no authentication process is required, you can create a dummy module that publishes a successful login.


No comments:

Post a Comment