Security

Labels
AJAX(112) App Studio(7) Apple(1) Application Builder(245) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcode(2) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(12) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(177) Device(1) DotNetNuke(12) EASE(20) Email(6) Features(101) Firebird(1) Form Builder(14) Globalization and Localization(6) How To(1) Hypermedia(2) Inline Editing(1) Installation(5) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(18) OAuth(9) OAuth Scopes(1) OAuth2(13) Offline(20) Offline Apps(4) Offline Sync(5) Oracle(11) PKCE(2) Postgre SQL(1) PostgreSQL(2) PWA(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(183) Reports(48) REST(29) RESTful(29) RESTful Workshop(15) RFID tags(1) SaaS(7) Security(81) SharePoint(12) SPA(6) SQL Anywhere(3) SQL Server(26) SSO(1) Stored Procedure(4) Teamwork(15) Tips and Tricks(87) Tools for Excel(2) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(338) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(40) Web.Config(9) Workflow(28)
Archive
Blog
Security
Tuesday, March 6, 2012PrintSubscribe
User ID, User Name, and Portal ID in Business Rules

Traditional ASP.NET application can determine the identity of the user by inspecting Page.User.Identity property of the page or user control class implementation.

Code On Time applications separate the business logic implementation from the presentation. An application page defines a markup with data placeholders. Page components inject the JavaScript client library initialization instructions in the output when a page is rendered. The JavaScript code is executed by the web browser. Initialized JavaScript classes start communicating with the business rules attached to the application data controllers by executing JSON requests.

Developers can access the user identity by inspecting the Context property available in the  BusinessRules class.

Example:

namespace MyCompany.Rules
{
    public partial class SharedBusinessRules : 
MyCompany.Data.BusinessRules { public SharedBusinessRules() { string userName = Context.User.Identity.Name; } } }

User ID can be determined by inspecting the properties of classes System.Security.Principal.WindowsIdentity and System.Web.Security.Membership.

Class BusinessRules offers convenient shortcuts. Static properties UserId, UserName, and PortalId.

The following implementation of SharedBusinessRules shows the examples of accessing identity properties of the base business rules class in a DotNetNuke Factory project. The same example will work in any other project with the exception of the line inspecting the Portal ID.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.DnnDemo.Data;

namespace MyCompany.DnnDemo.Rules
{
    public partial class SharedBusinessRules : 
        MyCompany.DnnDemo.Data.BusinessRules
    {
        
        public SharedBusinessRules()
        {
            object uid = UserId;
            string uname = UserName;
            int pid = PortalId;
        }
    }
}

Visual Basic:

Imports MyCompany.DnnTestVB.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq

Namespace Rules
    
    Partial Public Class SharedBusinessRules
        Inherits MyCompany.DnnTestVB.Data.BusinessRules
        
        Public Sub New()
            Dim uid As Object = UserId
            Dim uname As String = UserName
            Dim pid As String = PortalId
        End Sub
    End Class
End Namespace

Use these properties to implement access control rules that will filter data in multi-tenant web applications.

For example, the following access control rule will be invoked whenever the UserID data field is detected in the view of any data controller.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.DnnDemo.Data;

namespace MyCompany.DnnDemo.Rules
{
    public partial class SharedBusinessRules : 
        MyCompany.DnnDemo.Data.BusinessRules
    {
        [AccessControl("", "UserId", "[UserID] = @UserID")]
        public void FilterByUserUserID()
        {
            RestrictAccess("@UserID", UserId);
        }
    }
}

Visual Basic:

Imports MyCompany.DnnTestVB.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq

Namespace Rules
    
    Partial Public Class SharedBusinessRules
        Inherits MyCompany.DnnTestVB.Data.BusinessRules

        <AccessControl("", "UserId", "[UserId]=@UserId")>
        Public Sub FilterByUserId()
            RestrictAccess("@UserId", UserId)
        End Sub
    End Class
End Namespace

Thursday, March 1, 2012PrintSubscribe
View Filter Expressions

The alternative method of filtering is available in the data controller views. Property “View Filter” allows specifying an expression that will be embedded in the SQL statement composed by the application framework at runtime.

Suppose you want to filter a list of customers by a specific country.

Start the application generator and select your project, choose Design.

Locate the page Customers in Project Explorer, expand container1 and view1 nodes.

Double-click grid1 to active its properties.

Grid view "gird1" selected in Project Explorer

Enter the following expression in Filter Expression property of the Sort and Filter section.

Country = 'USA'

Sort and Filter section of a data controller view

Click OK button to save the changes and click Browse button on the tool bar. The generator will start the app in your default browser.

Navigate to Customers page and observe that only customers from the USA are displayed.

List of customers affected by the view filter Country = 'USA'

Select any customer by clicking on a link in the first column. The form view editForm1 will be activated.

Form view 'editForm1' inherits the filter from the last view 'grid1'. 

Notice that only customers from the USA are visible when you navigate between records in the form view with the help of navigation buttons.

Form view navigation buttons

The form view automatically inherits the value of Filter Expression from the last view that was presented to the user.

Static view filters work great when you need to present several alternative views of data. Users cannot remove the view filters and apply their own criteria on top of the view filter expressions.

View filter can also reference properties of the business rules class associated with the data controller of the view.

For example, you can define the following filter that contains a parameter.

Country = 'USA' and Region = @RegionName

If you generate the application and navigate to the Customers page then you will see the following exception:

View 'grid1' uses a filter with 'RegionName' parameter. Business rules class of the controller must provide a value for this parameter. The filter is defined as (Country = 'USA' and Region = @RegionName).

The application framework does not know how to determine the value of RegionName.

Right-click the data view view1 in the Project Explorer and choose Show Controller option.

"Show Controller" option in the context menu of data view node

Double-click Customers controller on the Controllers tab of Project Explorer.

"Customers" controller selected on the Controllers tab of Project Explorer

Enter CustomersBusinessRules in the Handler property of the controller and click save.

Definition of business rules class name

Exit the Designer and proceed to generate the project.

Select the project name on the start page of web application generator and click Develop.

Visual Studio or Visual Web Developer will start.

Open ~/App_Code/Rules/CustomersBusinessRules.cs(vb) class and enter the definition of RegionName read-only property.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class CustomersBusinessRules : MyCompany.Data.BusinessRules
    {
        public string RegionName
        {
            get
            {
                return "OR";
            }
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq
Imports System.Xml
Imports System.Xml.XPath

Namespace MyCompany.Rules

    Partial Public Class CustomersBusinessRules
        Inherits MyCompany.Data.BusinessRules

        Public ReadOnly Property RegionName As String
            Get
                Return "OR"
            End Get
        End Property

    End Class
End Namespace

Navigate to the Customers page and observe that only customers from the state of Oregon are now visible.

List of customers affected by view filter (Country = 'USA' and Region = @RegionName)

Notice that the value returned by RegionName property of the business rules class does not become a part of SQL statement.  The application will compose a SELECT statement that incudes the view filter expression text with the resolved names of the data fields. An actual command parameter will be created . The property value will be assigned to the parameter value.

If you want to create a filtering expression as a dynamic fragment of SQL at runtime then consider using dynamic access control rules.

If more than one value needs to be passed to the view filter then consider changing the filter definition as follows (we have replaced “=” with “in”).

Country = 'USA' and Region in @RegionName

Change the property definition to return a list or an array of values.

C#:

public List<string> RegionName
{
    get
    {
        List<string> regions = new List<string>();
        regions.Add("OR");
        regions.Add("WA");
        return regions;
    }
}

Visual Basic:

Public ReadOnly Property RegionName As List(Of String)
    Get
        Dim regions As List(Of String) = New List(Of String)
        regions.Add("OR")
        regions.Add("WA")
        Return regions
    End Get
End Property

Customers from the states of Oregon and Washington are now available in the list.

List of customers filtered by array of (WA, OR)

The application framework will list a separate parameter in the composed SELECT statement for each value in the list returned by the RegionName property of the business rules class.  In our example the actual fragment of SQL will look as follows:

("Customers"."Country" = 'USA' and "Customers"."Region" in (@RegionName0,@RegionName1))

Wednesday, February 29, 2012PrintSubscribe
Dynamic On-Demand Filtering with Access Control Rules

Business requirements can change hourly in the world of broadband connections and instant messages . Your application will have to be changed no matter how good you are at putting together a detailed requirements specification for the project. Some obscure security rules will be missed, new clients will require special handling – you know the story.

It is virtually impossible to create an application that will adapt to changing security and data segregation requirements unless you are building your web applications with Code On Time.

The unique architecture of generated web applications allows dynamic engagement of access control rules without changing a single line in the source code of your project.

Consider the following screen shot of the Northwind sample with a seemingly random list of ten customer accounts.

Dynamic access control rules in action.

The actual web application source code defines a business rules class with an override of EnumerateDynamicAccessControlRules method. This method registers a few access control rules whenever the customer accounts are retrieved from the application database.

Here is the code.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class CustomersBusinessRules : MyCompany.Data.BusinessRules
    {

        protected override void EnumerateDynamicAccessControlRules(string controllerName)
        {
            RegisterAccessControlRule(
                "CustomerID", AccessPermission.Allow, "ANTON", "ANATR");

            RegisterAccessControlRule(
                "CustomerID",
                "[Country]=@Country and [ContactTitle] = @ContactTitle",
                AccessPermission.Allow,
                new SqlParam("@Country", "USA"),
                new SqlParam("@ContactTitle", "Owner"));

            RegisterAccessControlRule(
                "CustomerID",
                "select CustomerID from Customers " +
                "where Country=@Country2 and City=@City",
                AccessPermission.Allow,
                new SqlParam("@Country2", "UK"),
                new SqlParam("@City", "London"));
        }

    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq
Imports System.Xml
Imports System.Xml.XPath

Namespace MyCompany.Rules

    Partial Public Class CustomersBusinessRules
        Inherits MyCompany.Data.BusinessRules

        Protected Overrides Sub EnumerateDynamicAccessControlRules(controllerName As String)
            RegisterAccessControlRule(
                "CustomerID", AccessPermission.Allow, "ANTON", "ANATR")

            RegisterAccessControlRule(
                "CustomerID",
                "[Country]=@Country and [ContactTitle] = @ContactTitle",
                AccessPermission.Allow,
                New SqlParam("@Country", "USA"),
                New SqlParam("@ContactTitle", "Owner"))

            RegisterAccessControlRule(
                "CustomerID",
                "select CustomerID from Customers " +
                "where Country=@Country2 and City=@City",
                AccessPermission.Allow,
                New SqlParam("@Country2", "UK"),
                New SqlParam("@City", "London"))
        End Sub

    End Class
End Namespace

Let’s review the effect of each individual rule on our data set.

The first call of RegisterAccessControlRule method limits a list of customers to those with the specific customer IDs of ANTON and ANATR.

Customers with IDs of ANTON and ANATR.

The second call limits a list of customers to those from the USA and having the title of Owner.

Customers from the USA with the title of Owner.

The third call limits a list of customers to those from the United Kingdom and located in the city of London.

Customers from the United Kingdom located in the city of London.

The three calls are showcasing various methods of creating a dynamic restriction.

The final result is a cumulative set of 10 records since the rules do not contradict each other.

The access control rules used in the example are registered unconditionally  and hard-coded in the application business logic.

What if you take this rules and store them in the database? The rules can be loaded on-demand based on the user identity and injected in the application without changing anything at all. Better yet, you can enable shared business rules in your project and have only one implementation of EnumerateDynamicAccessControlRules method.

We leave the actual implementation up to you.

If a custom implementation of dynamic access control rules is too much for you or is simply not required then continue using the static access control rules.