Note: This expands on the code created in my previous post: Requiring Log-On in a WPF MVVM Composite Application
* Download Complete Source Code
Continuing on my WPF MVVM Adventures... Well, I am still waiting on the business to finalize the requirements so I am going to take a shot at coding it to what I think the final specs will be. Although this is a very common situation, when you take this slippery slope you need to be careful that you don’t end up creating throw away code. Make sure you:
The first thing I need is to define by security roles. Since the actual roles are TBD I am just going to create a simple Enumeration.
In thinking about what the Authentication method of my yet to be created service will return I decided it was going to need to return multiple things.
Knowing I was going to need to return multiple values I created a data transfer object (DTO) to handle it.
Now I can create my service. This is going to reside in my Infrastructure project and will allow me to push(abstract) the implementation of the actual authentication farther down the stack. Sticking to what I recommended at the beginning of this post I am going to create a simple interface for the service. The interface will declare one signature, Authenticate, that accepts a username and password and returns an AuthenticationContext.
Next we need to code the actual implementation of IAuthenticationService. At this time the implementation of Authenticate will need to perform the actual authentication, which will set the IsAuthorized flag as well as the AuthLevel, and determine what modules are viewable for the AuthLevel. Because I still have not defined the details of these process I am going to “stub” them out with a trivial implementation.
Now we need to hop over the Shell project and start making adding in the hooks for our module level security.
This first I am going to do is change how the modules are loaded. Initially I used the ConfigurationModuleCatalog which loads the modules from a configuration file. I decided against this approach because I wanted to avoid configuration changes when a module was added or removed. Luckily Prism provides another option called the DirectoryModuleCatalog. This allows you to supply a directory path that contains the dll’s for your modules. So, all that needs to be done in order to add a new module is to drop its dll’s in that directory. This change needs to implemented in the bootstrapper and while we are in there we need to tell our IOC container how to wire up our AuthenticationService.
So now that we did that we can more easily add new modules but it’s still all or nothing. We need to tell Prism to not load certain modules until we tell it to…load on demand. This is accomplished by simply by decorating the modules you want to load on demand with the Module attribute and setting the ModuleName and OnDemand properties. As you can guess we are going to set the OnDemand property to “True”. This tells Prism, when it is processing the modules in the directory we tell it, not to load the module just yet. Prism notes the name of the module and waits for us to tell it when to load it. We will do this on the EmployeeEditModule, and EmployeeCreateModule which will both require authorization but we will not do this to the EmployeeListModule because that module is viewable by all.
Now when you run the the shell you won’t be able to edit or create a new employee because those modules are not loaded which means that nothing is registered to the associated commands.
We already have the list of allowed secured modules being returned from the authentication service so we just need to write a method to process the list and load the modules. This method will be in the Bootstrapper and it will load the allowed secured modules using the Module Manager.
Lastly we need to call LoadSecuredModules. We will do this as the last step in the App.xaml’s StartUp method.
Now when we log in with a read-only id (readonly,pass) the edit and create new buttons are not enabled because the modules are not loaded.
Keith is a Senior Software Engineer with Falafel Software. He has been developing software since 1999 specializing in web-based solutions primarily using the Microsoft stack. He has been a Microsoft MVP in ASP.NET since 2012.
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.