There are many reasons why Security is a necessity when developing even the simplest online shop backend. Instead of listing them all I will concentrate on how to empower the application prototype we created for our DXSK8 e-shop with a flexible Security System.
You may recall that in the previous post we applied a XAF layer(rich application) over an EF model located in an external lib (DSK8.Service). Now we will extend the same EF model to support XAF’s Security System.
1) Designing an Entity Framework Model for Security System objects.
XAF’s Security system uses Users,Roles and Permissions to configure both data access and UI generation for both platforms! This is done with the help of several system interfaces such as :
User: ISecurityUser, IAuthenticationStandardUser, IOperationPermissionProvider
Role:, IOperationPermissionProvider.
Our EF model from the DXSK8.Service project already contains an Employee entity, which is just perfect for taking on the role of XAF’s system user. We begin by adding all public properties of the user depended interfaces to our Employee entity. XAF interfaces are well designed and there are only three as you see below. The UserName in the black frame already existed in our Login entity, it’s not in the Employee entity with the rest of the new fields. XAF has no problems understand it as is!
The next step is to design the Roles and Permissions objects. While XAF supports member level and criteria based systems as well, I will utilize the Type Permission system in this case. I only need the Roles and TypePermissionObject entities listed below.
Be sure to follow the database migration steps detailed by EF. For the purposes of this blog I followed a standard technic described in Code First Migrations.
Note that we must use partial classes to implement the consumed interfaces this implementation simple and can be reusable, for example let’s see how easy it is to implement the Employee interfaces. For Role, TypePermissionObject implementation please check sample at the end of the post (See also How to: Implement Custom Security Objects (Users, Roles, Operation Permissions))).
[ImageName("BO_User"), DefaultProperty("UserName")]
publicpartialclassEmployee : ISecurityUser, IAuthenticationStandardUser,
IOperationPermissionProvider {
#region IOperationPermissionProvider
IEnumerable<IOperationPermissionProvider> IOperationPermissionProvider.GetChildren() {
if (!Roles.IsLoaded) {
Roles.Load();
}
returnnewEnumerableConverter<IOperationPermissionProvider, Role>(Roles);
}
IEnumerable<IOperationPermission> IOperationPermissionProvider.GetPermissions() {
returnnewIOperationPermission[0];
}
#endregion
#region ISecurityUser
BooleanISecurityUser.IsActive {
get { returnIsActive.HasValue&& IsActive.Value; }
}
StringISecurityUser.UserName {
get { returnUserName; }
}
#endregion
#region IAuthenticationStandardUser
BooleanIAuthenticationStandardUser.ComparePassword(String password) {
var passwordCryptographer = newPasswordCryptographer();
return passwordCryptographer.AreEqual(StoredPassword, password);
}
publicvoidSetPassword(String password) {
var passwordCryptographer = newPasswordCryptographer();
StoredPassword = passwordCryptographer.GenerateSaltedPassword(password);
}
BooleanIAuthenticationStandardUser.ChangePasswordOnFirstLogon {
get { returnChangePasswordOnFirstLogon.HasValue&& ChangePasswordOnFirstLogon.Value; }
set { ChangePasswordOnFirstLogon = value; }
}
StringIAuthenticationStandardUser.UserName {
get { returnUserName; }
}
#endregion
}
2) Installing a XAF Security System
Although XAF has strong design time support I will go through this step using one line of code in both Program.cs and Global.asax.cs just before application.Setup() call.
application.Security = newSecurityStrategyComplex(typeof(DXSK8.Service.Employee), typeof(DXSK8.Service.Role), newAuthenticationStandard());
application.Setup();
The snippet above will assist you with applying a security strategy using the Entity Framework entities located in the external DXSk8.Service lib . For this type of security strategy XAF spares our time as usual and will automatically display a customizable credentials window for both win and web platforms as shown,
In addition XAF detects the custom Security EF Entities we designed in step 1 and automatically populates the navigation menu.
Win | Web |
3) Supplying initial data
It is absolutely imperative that someone working on your project is assigned the security password. In addition, a user with admin privileges must also be assigned. Use the XafApplication’s CustomCheckCompatibility event inside our platform agnostic module to assign these admin priviledges.
publicoverridevoidSetup(XafApplication application) {
base.Setup(application);
application.CustomCheckCompatibility+=ApplicationOnCustomCheckCompatibility;
application.CreateCustomObjectSpaceProvider+=ApplicationOnCreateCustomObjectSpaceProvider;
}
voidApplicationOnCustomCheckCompatibility(object sender, CustomCheckCompatibilityEventArgs e) {
var objectSpace = e.ObjectSpaceProvider.CreateUpdatingObjectSpace(true);
var updater = newUpdater(objectSpace, Version.Parse("1.0.0.0"));
updater.UpdateDatabaseAfterUpdateSchema();
}
and the UpdateDatabaseAfterUpdateSchema where we created:
a) A Content Manager role with CRUD on Product but ReadOnly on Orders/Employees
b) A Sales Manager role wirh CRUD on Order but ReadOnly on Product/Employees
publicoverridevoidUpdateDatabaseAfterUpdateSchema() {
base.UpdateDatabaseAfterUpdateSchema();
if (ObjectSpace.FindObject<Employee>(CriteriaOperator.Parse("UserName=?","Admin")) == null) {
var roleAndUser = CreateRoleAndUser("Admin");
roleAndUser.IsAdministrative = true;
CreateRole("Content Manager", new[]{
CRUDPermission(typeof(Product)),
ReadOnlyPermission(typeof(Order)),
ReadOnlyPermission(typeof(Employee))
});
CreateRole("Sales Manager", new[]{
CRUDPermission(typeof(Order)),
ReadOnlyPermission(typeof(Product)),
ReadOnlyPermission(typeof(Employee))
});
var employees = ObjectSpace.GetObjects<Employee>();
foreach (varemployeein employees) {
employee.IsActive = true;
employee.ChangePasswordOnFirstLogon = true;
}
ObjectSpace.CommitChanges();
}
}
Use this post’s sample to explore the implementation of the remaining methods, which happens to be rather simple.
The remainder of the project needs a business user to simply associate Employees with Roles using XAF’s well thought-out UI. For example, the next two screenshots illustrate how to assign a Content Manager Role to a list of users.
Conclusion
There are many difficulties and complexities when it comes to addressing business problems with technology. And that’s exactly why tools like XAF, which bridge business and technology are such a life saver. You just witness just how simple it was to integrate a complex and sensitive feature like security while working with EF as datalayer. Thanks to the flexible and well-designed XAF, your product can now be marketed more easily since it features a complete security system.
I close this time with a phrase I often hear from our customers :
XAF really works!
Download a sample from here and attach the mdf file found in the DXSK8.Service/App_Data folder to your SQL instance. Be sure to visit How to: Get Started with the Entity Framework Model First in XAF for coverage of the basics.
.