Translate

Monday, 14 March 2016

Custom Service Authorization Manager for WCF Service

The IT industry divides security into two parts: 

1. Authentication 2. Authorization. 

Authentication verifies that users are who he claims to be. This can be done in a couple of ways: certificates, username/password, windows credentials, …

Authorization will decide what an (authenticated) user is allowed to execute. 

Implementing restricted access to a WCF service can be done in a couple of ways. 
  • A first option is to mark methods with the declarative PrincipalPermissionAttribute to restrict access to certain roles or users. 
  • An another option is to imperatively check the credentials of the current user.

Both of these methods have the drawback that they result in a lot of duplication when you have multiple service methods. Because duplication is the root of all evil, the creators of WCF have foreseen an extension point in WCF to implement authorization in a generic way: the ServiceAuthorizationManager.

Generic implementation to authorize access to a WCF service:

Implementation


Implementing a ServiceAuthorizationManager is straightforward; you need to extend the class “ServiceAuthorizationManager” and you need to override the method “CheckAccessCore”. In this small example, I will restrict access to my service to users of the windows group “Administrators”.

public class MyServiceAuthorizationManager : ServiceAuthorizationManager
{
    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        try
        {
            ServiceSecurityContext securityContext = operationContext.ServiceSecurityContext;
            WindowsIdentity callingIdentity = securityContext.WindowsIdentity;
 
            WindowsPrincipal principal = new WindowsPrincipal(callingIdentity);
            return principal.IsInRole("Administrators");
        }
        catch (Exception)
        {
            return false;
        }
    }
}

Now that our custom ServiceAuthorizationManager has been implemented, we need to hook it into the WCF pipeline. The most easy way to do is, by using the web.config or app.config file.

<system.serviceModel>
   <!-- Define service and endpoints --> 
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServiceBehavior">
                <serviceAuthorization serviceAuthorizationManagerType="MyNamespace.MyServiceAuthorizationManager, MyAssembly" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>


Wednesday, 24 February 2016

MERGE SQL Server

1. it is an efficient way to perform multiple DML operations.

2. the most important advantage of MERGE statement is all the data is read and processed only once.

3. using MERGE statement we can include the logic of such data modifications in one statement that even checks when the data is matched then just update it and when unmatched then insert it.

4. This is quite an improvement in performance of database query.

Example,
-- Update existing, add missing
MERGE INTO dbo.tbl_Customers AS C
USING dbo.tbl_CustomersTemp AS CT
        ON C.CustID = CT.CustID
WHEN MATCHED THEN
    UPDATE SET
      C.CompanyName = CT.CompanyName,
      C.Phone = CT.Phone
WHEN NOT MATCHED THEN 
      INSERT (CustID, CompanyName, Phone)
      VALUES (CT.CustID, CT.CompanyName, CT.Phone)

CREATE TABLE dbo.tbl_Source (id INT, name NVARCHAR(100), qty INT);
CREATE TABLE dbo.tbl_Target (id INT, name NVARCHAR(100), qty INT);

--Synchronize source data with target
MERGE INTO dbo.tbl_Target AS t
    USING dbo.tbl_Source AS s    
        ON t.id = s.id
    WHEN MATCHED AND (t.name != s.name OR t.qty!= s.qty) THEN
        --Row exists and data is different
        UPDATE SET t.name = s.name, t.qty = s.qty
    WHEN NOT MATCHED THEN 
        --Row exists in source but not in target
        INSERT VALUES (s.id, s.name, s.qty) 
    WHEN SOURCE NOT MATCHED THEN 
        --Row exists in target but not in source
        DELETE OUTPUT$action, inserted.id, deleted.id