Tuesday, September 25, 2012

Something about user access control or security control design

Below is a few strategy to implement the user access control or the security feature in your application.

  1. The simplest design will be user name + password and stores these information in a database table. No control over the feature accessibility.
  2. One level harder will be using one security "action" to treat as one permission. And one security action represent a menu option, button, input field, display field or a process to be executed. This design requires 1 user class and a collection of permitted/allowed security actions. So, you need two database tables to stores the information. For example, user A allows issuing and editing invoice but not deleting any invoice. In this case, you will have 3 allowed actions (or record) for user A.
  3. In case you feel that having one security action mapping to the feature is cumbersome and require lots of hard space, you may consider adding a flag field in the security action. For example, "Invoice" action will have 3 flags: issue, edit and delete where the "flag" is in BIT data type (in MSSQL database). If the flag value is "1" means permitted and "0" means not permitted.
  4. Some applications requires another level of sophistication - that is using "user level" in conjunction with the security actions.
  5. Another kind of implementation is to have write level (0-10) and read level (0-10). Both values are use in conjunction with the menu option and input fields. For example, the credit limit field for the customer has read level of "5" and write level of "8". If the user's read level is "5" and the user will be able to view the credit limit field. If the user's write level is also "5", then, this credit limit value will be disabled from editing. 
So, which one is better? It's all depend on your need. As for us, we prefer #2 due to easier to implement and future enhancement. It's also very easy to cater for changes.

Let's assume that you read the previous article, the CUser class will have a CanAccess() method which returns true or false. The application should check the result of this method before performing the process/action whereas CUser class.

Different flavor of CanAccess()
  • bool CanAccess(Guid action_id)
  • bool CanAccess(Guid action_id, PermissionEnum permission) [PermissionEnum {insert, update, delete, select]
  • bool CanAccess(Guid action_id, int user_level)
  • bool CanAccess(int read_level, int write_level)

Thursday, September 20, 2012

Reusable class - user access control

This is another important area in the systems and it is reusable as long as the design is generic to cover all possible combination.

Basically, it should meet the following requirements:
  • Security control - allows user to logon to the system and verify their user name and password.
  • Access permission - permission could be controlled by menu level, screen level and field level (whether the field is show/hidden or enable/disable).
  • User access log - this is compulsory for audit purpose and also the alert.
  • Access deny alert - upon hitting certain number of invalid user name or password, the system should generate alert and email it to the system administrator.
  • Password policy - you may consider to implement minimum password length and password complexity.
  • Allow supervisor overriding - this can be useful when the current user does not have permission to access certain feature (such as edit customer address) but requires to do so.
  • In case the system is a web base system, it should store the browser type and visitor IP address for audit purpose.
 You need the following classes to support the above mentioned requirements:
  1. CUser - this class stores the user information such as user name, password, email address, etc.
  2. CAction - this class stores all the permissions (or features) for the system.
  3. CUserAccessLog - this class responsible for keeping track the user login and logout activities.
  4. CLog - this class (which has been discussed in previous article) which is responsible for storing the audit information such as which "action" (or "featuer") the user has clicked.
For the detailed implementation, you might have work it out by yourself.

Monday, September 3, 2012

Reusable class - System log - the information for troubleshooting

In our system design, we are trapping all the exceptions that raised up at runtime and store it into a central database. This allows us to provide faster response time in fixing the error before the user complains. I know many people will ask why there is an error and why it was not catch at the development or testing phase. The answer is simple, we are not developing standard package. Almost all projects come with different requirements except for the "infrastructure" (such as the security, application log, etc).

To log down the exception, this error logging process should done in a very short time so that it won't affect the system performance or other processes. This can be achieve by saving the exception using a different thread.

In our system logging class, we have the following methods:
  • AppendLog - this save the log as "audit log".
  • AppendError - this save the exception and the failure point as "error".
  • AppendWarning - this save the log as "warning" and it is very useful when the system setting is missing or misconfigure.
To track the failure point, refer to System.Diagnostics.StackTrace class.
To save the log information in another thread, refer to System.Threading.ThreadPool.

Our application log table design:

http://sqllauhw2000.blogspot.com/2012/07/you-need-application-log-for-your.html