printer

Custom Membership And Role Provider for Sitefinity

Problem description

Development of an extranet website, based on Sitefinity, with two kind of users:

  • Administrators: are responsible for managing the website within the Sitefinity CMS environment.
  • Dealers: can view the pages in the website but should not be able to see the Sitefinity CMS environment.

The homepage of the extranet website should show a Login screen where dealer can login. After a successful authentication, the rest of the website is shown.
Administrators will logon with the standard Sitefinity login page. The dealers, who are authorized to view the website, are stored in another database (Microsoft SQL Server 2005) than the CMS database of Sitefinity. 

Considerations
 
Because the administration of Sitefinity can use only one set of providers at a time, it is not possible to use the Sitefinity membership - and role providers for authorizing the administrators and a separate custom membership and role provider for authorizing the dealers.
Therefore the decision is made to develop a custom membership and role provider to manage administrators as well as dealers. This means that the administrators, the roles and the relation between the users and roles are also stored in this separate database. 

Database schema

The dealers are stored in an existing database table, called dealers. This table should have at least a user name and a user password field because those are the two fields to validate the user. In this situation user address, user email, user phone fields etc. are defined also.

CREATE TABLE [dbo].[dealers]( 
        [customer_nr] [nvarchar](30) NULL, 
        [customer_name] [nvarchar](255) NULL, 
        [password] [nvarchar](20) NULL, 
        [address] [nvarchar](35) NULL, 
        [zipcode] [nvarchar](7) NULL, 
        [city] [nvarchar](25) NULL, 
        [phone] [nvarchar](16) NULL, 
        [fax] [nvarchar](16) NULL, 
        [email] [nvarchar](200) NULL,
) ON [PRIMARY]


New roles must be stored in the role table. Because the existing database didn’t have this role table, it was created .

CREATE TABLE [dbo].[role]( 
        [roleID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_role_roleID] DEFAULT (newid()), 
        [applicationname] [nvarchar](256) NOT NULL, 
        [rolename] [nvarchar](256) NOT NULL,
CONSTRAINT [PKRole] PRIMARY KEY CLUSTERED

        [rolename] ASC, 
        [applicationname] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]


On the other hand the relation between dealers and their role must be stored also in the database. Because the existing databse didn’t have this role relation table, it was created.

CREATE TABLE [dbo].[dealer_in_role]( 
        [customer_nr] [nvarchar](50) NOT NULL, 
        [rolename] [nvarchar](256) NOT NULL, 
        [applicationname] [nvarchar](256) NOT NULL,
CONSTRAINT [PKUsersInRoles] PRIMARY KEY CLUSTERED

        [customer_nr] ASC, 
        [rolename] ASC, 
        [applicationname] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]


If is is necessary to store extra metainfo, one can decide to create another dealer_metainfo table, but for this situation it was not necessary.
 

Custom Membership Provider

Actions to create the custom membership provider:

  • Open your Sitefinity project in Visual Studio 2005
  • Create a App_Code folder in this project if it is not already available
  • Create a new class ‘CustomMembershipProvider’ in this folder App_Code
  • The class CustomMembershipProvider must be inherited from MembershipProvider
  • Because MembershipProvider is an abstract class, we need to override all the abstract methods in the CustomMembershipProvider class. There is a very cool feature in Visual Studio 2005 that does this automatically. As soon as you extend any abstract class, just right-click Abstract class, and then click Implement Abstract Class. This automatically places declarations for all the abstract methods.
  • You will notice that the body for each method contains a common line of code.
  • For this situation only specific methods were implemented. Below you find the complete implementation of the CustomMembershipProvider class:

using System;
using
System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Specialized;
using System.Data.SqlClient;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.SessionState;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;


/// <summary>
/// Summary description for CustomMembershipProvider
/// </summary>
public class CustomMembershipProvider: MembershipProvider
{
 public CustomMembershipProvider()
 {
  //
  // TODO: Add constructor logic here
  //
 }

    private string _name;

    public override void Initialize(string name, NameValueCollection config)
    {
        // Verify that config isn't null
        if (config == null)
            throw new ArgumentNullException("config");

        // Assign the provider a default name if it doesn't have one
        if (String.IsNullOrEmpty(name))
            name = "CustomProvider";

        _name = name;

        // Add a default "description" attribute to config if the
        // attribute doesn't exist or is empty
        if (string.IsNullOrEmpty(config["description"]))
        {
            config.Remove("description");
            config.Add("description", "Custom SQL Provider");
        }

        // Call the base class's Initialize method
        base.Initialize(name, config);
    }

    public override string ApplicationName
    {
        get
        {
            throw new Exception("The method or operation is not implemented.");
        }
        set
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }

    public override bool ChangePassword(string username, string oldPassword, string newPassword)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override bool DeleteUser(string username, bool deleteAllRelatedData)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override bool EnablePasswordReset
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override bool EnablePasswordRetrieval
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
    {
        SqlConnection cnn = null;
        SqlCommand cmd = null;
        MembershipUserCollection users = new MembershipUserCollection();
        try
        {
            totalRecords = 0;
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();
            string selectQry = "SELECT * FROM dealers ";
            cmd = new SqlCommand(selectQry, cnn);
            SqlDataReader rdr = cmd.ExecuteReader();
            if (rdr == null) return null;
            while (rdr.Read())
            {
                totalRecords++;
                MembershipUser user = new MembershipUser(_name, rdr["customer_nr"].ToString(), rdr["customer_name"], rdr["email"].ToString(), "", "", true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
                users.Add(user);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            cmd.Dispose();
            cnn.Close();
        }
        return users;
    }

    public override int GetNumberOfUsersOnline()
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override string GetPassword(string username, string answer)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        SqlConnection cnn = null;
        SqlCommand cmd = null;
        MembershipUser user = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();
            string selectQry = "SELECT * FROM dealers ";
            selectQry = selectQry + "WHERE customer_nr='" + username + "' ";
            cmd = new SqlCommand(selectQry, cnn);
            SqlDataReader rdr = cmd.ExecuteReader();
            if (rdr.Read())
                user = new MembershipUser(_name, rdr["customer_nr"].ToString(), rdr["customer_name"], rdr["email"].ToString(), "", "", true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            cmd.Dispose();
            cnn.Close();
        }
        return user;
    }

    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override string GetUserNameByEmail(string email)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override int MaxInvalidPasswordAttempts
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override int MinRequiredNonAlphanumericCharacters
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override int MinRequiredPasswordLength
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override int PasswordAttemptWindow
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override MembershipPasswordFormat PasswordFormat
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override string PasswordStrengthRegularExpression
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override bool RequiresQuestionAndAnswer
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override bool RequiresUniqueEmail
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override string ResetPassword(string username, string answer)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override bool UnlockUser(string userName)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public override void UpdateUser(MembershipUser user)
    {
        //throw new Exception("The method or operation is not implemented.");
        return;
    }

    public override bool ValidateUser(string username, string password)
    {
        SqlConnection cnn = null;
        SqlCommand cmd = null;
        bool userExists = true;
        try
        {
            string quotedUserName = username.Replace("'", "''");
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();
            string selectQry = "SELECT * FROM dealers ";
            selectQry = selectQry + "WHERE ((customer_name='"+ quotedUserName + "') ";
            selectQry = selectQry + "OR (customer_nr='" + quotedUserName + "')) ";
            selectQry = selectQry + "AND password='" + password + "' ";
            cmd = new SqlCommand(selectQry, cnn);
            SqlDataReader rdr = cmd.ExecuteReader();
            if (!rdr.Read())
                userExists = false;
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            cmd.Dispose();
            cnn.Close();
        }
        return userExists;
    }
}


Custom Role Provider

Actions to create the custom role provider:

  • Open your Sitefinity project in Visual Studio 2005 if it is not already open
  • Create a new class ‘CustomRoleProvider’ in the folder App_Code
  • The class CustomRoleProvider must be inherited from RoleProvider
  • Because RoleProvider is an abstract class too, we need to override all the abstract methods in the CustomRoleProvider class
  • Below you find the complete implementation of the CustomRoleProvider class:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Specialized;
using System.Data.SqlClient;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/// <summary>
/// Summary description for CustomRoleProvider
/// </summary>
public class CustomRoleProvider: RoleProvider
{
    public CustomRoleProvider()
 {
  //
  // TODO: Add constructor logic here
  //
 }

    private string _name;
    private string _applicationName;

    public override void Initialize(string name, NameValueCollection config)
    {
        // Verify that config isn't null
        if (config == null)
            throw new ArgumentNullException("config");

        // Assign the provider a default name if it doesn't have one
        if (String.IsNullOrEmpty(name))
            name = "CustomProvider";

        _name = name;

        // Add a default "description" attribute to config if the
        // attribute doesn't exist or is empty
        if (string.IsNullOrEmpty(config["description"]))
        {
            config.Remove("description");
            config.Add("description", "Custom SQL Role Provider");
        }

        if (config["applicationName"] == null || config["applicationName"].Trim() == "")
        {
            _applicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
        }
        else
        {
            _applicationName = config["applicationName"];
        }

        // Call the base class's Initialize method
        base.Initialize(name, config);
    }

   public override void AddUsersToRoles(string[] usernames, string[] roleNames)
    {
        foreach (string rolename in roleNames)
        {
            if (!RoleExists(rolename))
            {
                throw new Exception("Role name not found.");
            }
        }

        foreach (string username in usernames)
        {
            if (username.Contains(","))
            {
                throw new ArgumentException("User names cannot contain commas.");
            }

            foreach (string rolename in roleNames)
            {
                if (IsUserInRole(username, rolename))
                {
                    throw new Exception("User is already in role.");
                }
            }
        }

        SqlConnection cnn = null;
        SqlCommand cmd = null;
        SqlTransaction tran = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();
            string selectQry = "INSERT INTO dealer_in_role (customer_nr, rolename, applicationname) Values(@customer_nr, @rolename, @applicationname)";
            cmd = new SqlCommand(selectQry, cnn);

            SqlParameter userParm = cmd.Parameters.Add("@customer_nr", SqlDbType.VarChar, 255);
            SqlParameter roleParm = cmd.Parameters.Add("@rolename", SqlDbType.VarChar, 255);
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            tran = cnn.BeginTransaction();
            cmd.Transaction = tran;

            foreach (string username in usernames)
            {
                foreach (string rolename in roleNames)
                {
                    userParm.Value = username;
                    roleParm.Value = rolename;
                    cmd.ExecuteNonQuery();
                }
            }

            tran.Commit();

        }
        catch (SqlException ex)
        {
            try
            {
                tran.Rollback();
            }
            catch { }

            throw ex;
        }
        finally
        {
            cnn.Close();
        }
    }

    public override string ApplicationName
    {
        get { return _applicationName; }
        set { _applicationName = value; }
    }

    public override void CreateRole(string roleName)
    {
        if (roleName.Contains(","))
        {
            throw new ArgumentException("Role names cannot contain commas.");
        }

        if (RoleExists(roleName))
        {
            throw new Exception("Role name already exists.");
        }

        SqlConnection cnn = null;
        SqlCommand cmd = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();
            string selectQry = "INSERT INTO role (rolename, applicationname) Values(@rolename, @applicationname)";
            cmd = new SqlCommand(selectQry, cnn);

            cmd.Parameters.Add("@rolename",  SqlDbType.VarChar, 255).Value = roleName;
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            cmd.ExecuteNonQuery();
        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            cnn.Close();
        }
    }

    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
    {
        if (!RoleExists(roleName))
        {
            throw new Exception("Role does not exist.");
        }

        if (throwOnPopulatedRole && GetUsersInRole(roleName).Length > 0)
        {
            throw new Exception("Cannot delete a populated role.");
        }

        SqlConnection cnn = null;
        SqlCommand cmd = null;
        SqlCommand cmd2 = null;
        SqlTransaction tran = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();
            string selectQry = "DELETE FROM role WHERE rolename = @rolename AND applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);

            cmd.Parameters.Add("@rolename", SqlDbType.VarChar, 255).Value = roleName;
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            selectQry = "DELETE FROM dealer_in_role WHERE rolename = @rolename AND applicationname = @applicationname";
            cmd2 = new SqlCommand(selectQry, cnn);

            cmd2.Parameters.Add("@rolename", SqlDbType.VarChar, 255).Value = roleName;
            cmd2.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            tran = cnn.BeginTransaction();
            cmd.Transaction = tran;
            cmd2.Transaction = tran;

            cmd2.ExecuteNonQuery();
            cmd.ExecuteNonQuery();

            tran.Commit();
        }
        catch (SqlException ex)
        {
            try
            {
                tran.Rollback();
            }
            catch { }

            throw ex;
        }
        finally
        {
            cnn.Close();
        }

        return true;
    }

    public override string[] FindUsersInRole(string roleName, string usernameToMatch)
    {
        string tmpUserNames = "";

        SqlConnection cnn = null;
        SqlCommand cmd = null;
        SqlDataReader rdr = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();

            string selectQry = "SELECT customer_nr FROM dealer_in_role WHERE customer_nr LIKE @customer_nrSearch AND rolename = @rolename AND applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);
            cmd.Parameters.Add("@customer_nrSearch", SqlDbType.VarChar, 255).Value = usernameToMatch;
            cmd.Parameters.Add("@rolename", SqlDbType.VarChar, 255).Value = roleName;
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            rdr = cmd.ExecuteReader();
            while (rdr.Read())
            {
                tmpUserNames += rdr.GetString(0) + ",";
            }
        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            if (rdr != null) { rdr.Close(); }
            cnn.Close();
        }

        if (tmpUserNames.Length > 0)
        {
            // Remove trailing comma.
            tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1);
            return tmpUserNames.Split(',');
        }

        return new string[0];
    }

    public override string[] GetAllRoles()
    {
        string tmpRoleNames = "";
        SqlConnection cnn = null;
        SqlCommand cmd = null;
        SqlDataReader rdr = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();

            string selectQry = "SELECT rolename FROM role WHERE applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            rdr = cmd.ExecuteReader();
            while (rdr.Read())
            {
                tmpRoleNames += rdr.GetString(0) + ",";
            }
        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            if (rdr != null) { rdr.Close(); }
            cnn.Close();
        }

        if (tmpRoleNames.Length > 0)
        {
            // Remove trailing comma.
            tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1);
            return tmpRoleNames.Split(',');
        }

        return new string[0];
    }

    public override string[] GetRolesForUser(string username)
    {
        string tmpRoleNames = "";
        SqlConnection cnn = null;
        SqlCommand cmd = null;
        SqlDataReader rdr = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();

            string selectQry = "SELECT rolename FROM dealer_in_role WHERE customer_nr = @customer_nr AND applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);
            cmd.Parameters.Add("@customer_nr", SqlDbType.VarChar, 255).Value = username;
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            rdr = cmd.ExecuteReader();
            while (rdr.Read())
            {
                tmpRoleNames += rdr.GetString(0) + ",";
            }
        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            if (rdr != null) { rdr.Close(); }
            cnn.Close();
        }

        if (tmpRoleNames.Length > 0)
        {
            // Remove trailing comma.
            tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1);
            return tmpRoleNames.Split(',');
        }

        return new string[0];
    }

    public override string[] GetUsersInRole(string roleName)
    {
        string tmpUserNames = "";
        SqlConnection cnn = null;
        SqlCommand cmd = null;
        SqlDataReader rdr = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();

            string selectQry = "SELECT customer_nr FROM dealer_in_role WHERE rolename = @rolename AND applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);
            cmd.Parameters.Add("@rolename", SqlDbType.VarChar, 255).Value = roleName;
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            rdr = cmd.ExecuteReader();
            while (rdr.Read())
            {
                tmpUserNames += rdr.GetString(0) + ",";
            }
        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            if (rdr != null) { rdr.Close(); }
            cnn.Close();
        }

        if (tmpUserNames.Length > 0)
        {
            // Remove trailing comma.
            tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1);
            return tmpUserNames.Split(',');
        }

        return new string[0];
    }

    public override bool IsUserInRole(string username, string roleName)
    {
        bool userIsInRole = false;

        SqlConnection cnn = null;
        SqlCommand cmd = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();

            string selectQry = "SELECT Count(*) FROM dealer_in_role WHERE customer_nr = @customer_nr AND rolename = @rolename AND applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);
            cmd.Parameters.Add("@customer_nr", SqlDbType.VarChar, 255).Value = username;
            cmd.Parameters.Add("@rolename", SqlDbType.VarChar, 255).Value = roleName;
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            int numRecs = (int)cmd.ExecuteScalar();

            if (numRecs > 0)
            {
                userIsInRole = true;
            }

        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            cnn.Close();
        }

        return userIsInRole;
    }

    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
    {
        foreach (string rolename in roleNames)
        {
            if (!RoleExists(rolename))
            {
                throw new Exception("Role name not found.");
            }
        }

        foreach (string username in usernames)
        {
            foreach (string rolename in roleNames)
            {
                if (!IsUserInRole(username, rolename))
                {
                    throw new Exception("User is not in role.");
                }
            }
        }

        SqlConnection cnn = null;
        SqlCommand cmd = null;
        SqlTransaction tran = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();
            string selectQry = "DELETE FROM dealer_in_role WHERE customer_nr = @customer_nr AND rolename = @rolename AND applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);

            SqlParameter userParm = cmd.Parameters.Add("@customer_nr", SqlDbType.VarChar, 255);
            SqlParameter roleParm = cmd.Parameters.Add("@rolename", SqlDbType.VarChar, 255);
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            tran = cnn.BeginTransaction();
            cmd.Transaction = tran;

            foreach (string username in usernames)
            {
                foreach (string rolename in roleNames)
                {
                    userParm.Value = username;
                    roleParm.Value = rolename;
                    cmd.ExecuteNonQuery();
                }
            }

            tran.Commit();

        }
        catch (SqlException ex)
        {
            try
            {
                tran.Rollback();
            }
            catch { }

            throw ex;
        }
        finally
        {
            cnn.Close();
        }
   
    }

    public override bool RoleExists(string roleName)
    {
        bool exists = false;

        SqlConnection cnn = null;
        SqlCommand cmd = null;
        try
        {
            cnn = new SqlConnection();
            cnn.ConnectionString = ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
            cnn.Open();

            string selectQry = "SELECT Count(*) FROM role WHERE rolename = @rolename AND applicationname = @applicationname";
            cmd = new SqlCommand(selectQry, cnn);
            cmd.Parameters.Add("@rolename", SqlDbType.VarChar, 255).Value = roleName;
            cmd.Parameters.Add("@applicationname", SqlDbType.VarChar, 255).Value = ApplicationName;

            int numRecs = (int)cmd.ExecuteScalar();

            if (numRecs > 0)
            {
                exists = true;
            }

        }
        catch (SqlException ex)
        {
            throw ex;
        }
        finally
        {
            cnn.Close();
        }

        return exists;
    }
}


Login user control

A new user control must be developed that can be dragged, from within the Sitefinity CMS environment, to the home page of the extranet website. This Login user control is connected to the CustomMembership provider. 

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Login.ascx.cs" Inherits="UserControls_Login" %><%@ Control Language="C#" AutoEventWireup="true" CodeFile="Login.ascx.cs" Inherits="UserControls_Login" %>
<asp:Login ID="Login" runat="server"
UserNameLabelText="User Name (customer number):"
MembershipProvider="CustomProvider"
DestinationPageUrl="~/extranet/home.aspx"
TextLayout="TextOnTop" TitleText="">
</asp:Login>



There is no other user behind code necessary:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class UserControls_Login : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{

}

}
 


Web.config

To change the provider for the entire CMS, you have to change the cms providers in the web.config. You have to change:

  • connectionStrings=>connection to the separate database
  • system.web=>rolemanager and membership
  • telerik => security => cmsProvidersName
  • telerik => security => providers => DefaultSecurityProvider => MembershipProvider and RoleProvider

.
<connectionStrings>
 <add name="Sitefinity" connectionString="data source=<host>;UID=<user>;Password=<password>;initial catalog=<Sitefinity dbase>” providerName="System.Data.SqlClient" />
  <add name="CustomConnectionString" connectionString="Data Source=<host>;User ID=<user>;Password=<password>;Initial Catalog=<separate dbase>" providerName="System.Data.SqlClient" />
</connectionStrings>
.
.
<roleManager enabled="true" cacheRolesInCookie="true" defaultProvider="Sitefinity">
 <providers>
  <clear />
  <add connectionStringName="DefaultConnection" applicationName="/" name="Sitefinity" type="Telerik.DataAccess.AspnetProviders.TelerikRoleProvider, Telerik.DataAccess" />
  <add name="CustomProvider" applicationName="CustomApplication" type="CustomRoleProvider"/>
 </providers>
</roleManager>
<membership defaultProvider="Sitefinity" userIsOnlineTimeWindow="15" hashAlgorithmType="">
 <providers>
  <clear/>
  <add name="Sitefinity" connectionStringName="DefaultConnection" type="Telerik.DataAccess.AspnetProviders.TelerikMembershipProvider, Telerik.DataAccess" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" passwordAttemptWindow="10" passwordStrengthRegularExpression="" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0"/>
  <add name="CustomProvider" applicationName="CustomApplication" type="CustomMembershipProvider" />
 </providers>
</membership>
.
.
<security defaultProvider="DefaultSecurityProvider" cmsProvidersName="CustomProvider">
 <roles>
  <clear/>
  <add name="Administrators" permission="Unrestricted"/>
  <add name="PublicUsers" permission="None"/>
 </roles>
 <providers>
  <clear/>
  <add name="DefaultSecurityProvider" connectionStringName="DefaultConnection" type="Telerik.Security.Data.DefaultSecurityProvider, Telerik.Security.Data" membershipProvider="CustomProvider" roleProvider="CustomProvider"/>
 </providers>
</security>