Introduction
Here, I will provide the details about how to implement custom configSection
in your application.
Suppose you want to create a configSection
for your custom membership implementation as below:
<memberships>
<member username="test" password="testpassword" role="client" />
<member username="hostuser" password="private" role="client,host" />
</memberships>
For this, you need to create the required classes as below.
MembershipElement.cs
public class MembershipElement : ConfigurationElement
{
[ConfigurationProperty("username", IsRequired = true, IsKey = true)]
public string Username
{
get { return base["username"] as string; }
set { base["username"] = value; }
}
[ConfigurationProperty("password", IsRequired = true, IsKey = false)]
public string Password
{
get { return base["password"] as string; }
set { base["password"] = value; }
}
[ConfigurationProperty("role")]
public string Role
{
get { return base["role"] as string; }
set { base["role"] = value; }
}
}
MembershipCollection.cs
public class MembershipCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new MembershipElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((MembershipElement)element).Username;
}
protected override string ElementName
{
get
{
return "member";
}
}
protected override bool IsElementName(string elementName)
{
return !String.IsNullOrEmpty(elementName) && elementName == "member";
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
public MembershipElement this[int index]
{
get
{
return base.BaseGet(index) as MembershipElement;
}
}
public MembershipElement this[string key]
{
get
{
return base.BaseGet(key) as MembershipElement;
}
}
}
MembershipConfigurationHandler.cs
public class MembershipConfigurationHandler : ConfigurationSection
{
[ConfigurationProperty("", IsDefaultCollection = true, IsKey = false, IsRequired = true)]
public MembershipCollection Members
{
get
{
return base[""] as MembershipCollection;
}
set
{
base[""] = value;
}
}
}
Now you are ready to use your custom configSection
in your application. Your application’s config file will have the elements as below:
<configSections>
<section name="memberships" type="Authentication.Configuration.MembershipConfigurationHandler, Authentication"/>
</configSections>
<memberships>
<member username="test" password="testpassword" role="client" />
<member username="hostuser" password="private" role="client,host" />
</memberships>
I have a created a helper class to access the member details with ease.
MembershipProvider.cs
public static class MembershipProvider
{
public static MembershipElement GetMember(string userName)
{
var memberships = ConfigurationManager.GetSection("memberships") as MembershipConfigurationHandler;
if(memberships == null || memberships.Members == null || memberships.Members.Count < 1)
return null;
return memberships.Members[userName];
}
public static MembershipElement ValidateUser(string userName, string password)
{
var member = GetMember(userName);
if (member != null && member.Password.Equals(password))
return member;
return null;
}
}
You can use this provider to validate the member or get the member details. I have used this provider in my application to authenticate the member and set the roles in current thread.
CustomUsernamePasswordValidator.cs
public class CustomUsernamePasswordValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
var member = MembershipProvider.ValidateUser(userName, password);
if(member == null)
throw new FaultException<SecurityTokenException>
(new SecurityTokenException("Authentication failed"),
"Unknown Username or Password");
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(userName),
member.Role.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
}
}
I have used this validator in WCF service application to validate using custom username and password. I will explain that in other post.
Appreciate your query and suggestions.
CodeProject