Monday, February 20, 2012

Securing an ASP.Net WebService

Implementing authentication for Webservice is quite simple. This is one of the several methods in implementing security for WebServices.

The WebService you created should have a custom SOAPHeader. We pass the credentials with  SOAPHeader to the server during the WebService calls and get it validated on server. The response of the WebMethod will be sent back only if the user is authenticated.

We will have to include the custom SOAPHeader that we want to include in the SOAP message.
For this, we will have to write a separate class(UserCredentials) which inherits from [System.Web.Services.Protocols.SoapHeader] with two properties. (UserName and Password)

My WebService to be hosted on a remote Server

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(Name = "KochiService", ConformsTo = WsiProfiles.BasicProfile1_1)]

public class KochiService : System.Web.Services.WebService {

public UserCredentials Credentials;
public KochiService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]
[SoapDocumentMethod(Binding = "KochiService")]
[SoapHeader("Credentials", Required= true)]
public string GetEmployeeSalary() {
if (AuthenticateUser())
{
   return "This user's Salary is 10,000";
}
else
{
    return "You are not authorised to consume this service";
}
}
private bool AuthenticateUser()
{
if ((Credentials.UserName == "Sabin") && (Credentials.Password == "1234"))
{
   return true;
}
else
{
   return false;
} 


}

For Security, 
Custom SOAP Header Class; User Credentials

using System;
using System.Collections.Generic;
using System.Web;

public class UserCredentials : System.Web.Services.Protocols.SoapHeader
{
    public string UserName;
    public string Password;
}


HOSTING THE WEB SERVICE.
Build the solution and deploy the WebService files on remote server.
.ASMX on the root of the Website or Virtual Directory and the .CS file in the App_Code of the ASP.Net Website.

Also make sure that the UserCredential class got deployed on the server under App_Code.
After hosting you will be able to view the details of the webservice by accessing the .ASMX page as www.MyWebsite.com/KochiService.asmx




Now, your WebService is available online for all the users. But only those pass the exact Credentials will ONLY be able to get the response from the remote machine(WebService).




CONSUMING THE WEBSERVICE

Those who have the correct Credentials for the WebService can access the service from anywhere in  a .Net Website over the internet. For accessing the WebService, we need to add the service through the ServiceReferance by right clicking on the WebSite Project in Visual Studio. While adding, it creates a proxy to call the service from the solution. 


Calling WebService from .aspx Page remotely

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class WebServiceCalls : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyServiceReference.KochiServiceClient oService = new MyServiceReference.KochiServiceClient();
MyServiceReference.UserCredentials oCredentials = new MyServiceReference.UserCredentials();

oCredentials.UserName = "Sabin";
oCredentials.Password = "1234";

Response.Write(oService.GetEmployeeSalary(oCredentials));

}
}


The service will return the response based on the authentication as below


Sunday, February 12, 2012

Sending XML to Stored Procedure


The need of sending a series of strings to Stored Procedure will be there in all most all the projects. XML variables in SQL Server make it easy to deal with XML strings into relational databases. The new methods we should use are value() and nodes() which allow us to select values from XML documents.



DECLARE @Employees xml
SET @Employees = '1908210174'

SELECT ParamValues.ID.value('.','VARCHAR(20)')
FROM @Employees.nodes('/Employees/id') as ParamValues(ID)



The above SQL statements returns three rows as below:
1908
2101
74

Now, let us see how this can be used to fetch the Employee information for a list of Employee Ids. Take a look at the Stored Procedure.

CREATE PROCEDURE GetEmployeesDetailsForThisList(@EmployeeIds xml) AS
DECLARE @Employees TABLE (ID int)

INSERT INTO @Employees (ID) SELECT ParamValues.ID.value('.','VARCHAR(20)')
FROM @EmployeeIds.nodes('/Employees/id') as ParamValues(ID)

SELECT * FROM
    EmployeeTable
INNER JOIN 
    @EmployeeIds e
ON    EmployeeTable.ID = e.ID

This Stored Procedure can be called as

EXEC GetEmployeesDetailsForThisList '1908210174'





XML public static string BuildEmployeesXmlString(string xmlRootName, string[] values)
{
    StringBuilder xmlString = new StringBuilder();

    xmlString.AppendFormat("<{0}>", xmlRootName);
    for (int i = 0; i < values.Length; i++)
    {
    xmlString.AppendFormat("{0}", values[i]);
    }
    xmlString.AppendFormat("", xmlRootName);
    return xmlString.ToString();
}

This above ASP.NET method will return XML String, and this can be sent as the input parameter to Stored Procedure