Sounds like you'll need to implement a custom MembershipProvider that inherits from ActiveDirectoryMembershipProvider.
At a minimum, you'll need to override ValidateUser
so that if the base.ValidateUser
returns false, you can attempt to validate the user in your SQL database. The following code sample works in my test application, however I did not implement the SQL method. That should be pretty straight forward for you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Configuration;
using System.Configuration.Provider;
namespace Research.Web.Security
{
public class MixedMembershipProvider : ActiveDirectoryMembershipProvider
{
protected String SqlConnectionString { get; private set; }
private String GetConnectionString(String connectionStringName)
{
if (string.IsNullOrEmpty(connectionStringName))
throw new ProviderException("ConnectionStringName must be specified.");
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[connectionStringName];
if (settings == null)
{
throw new ProviderException(String.Format("Connection string {0} not found.", connectionStringName));
}
return settings.ConnectionString;
}
public override void Initialize(String name, System.Collections.Specialized.NameValueCollection config)
{
this.SqlConnectionString = GetConnectionString(config["sqlConnectionStringName"]);
config.Remove("sqlConnectionStringName");
base.Initialize(name, config);
}
public override Boolean ValidateUser(String username, String password)
{
if (!base.ValidateUser(username, password)) // validate using AD first
{
return ValidateUserSql(username, password); // if not in AD, check SQL
}
else
{
return true;
}
}
private Boolean ValidateUserSql(String username, String password)
{
// look up your account in SQL here
return true;
}
}
}
Your web config would look something like this:
<configuration>
<!-- usual config stuff omitted -->
<connectionStrings>
<add name="SqlDefault" connectionString="Server=localhost;database=mydatabase;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
<add name="ActiveDirectoryDefault" connectionString="LDAP://mydomain.com/DC=mydomain,DC=com" />
</connectionStrings>
<system.web>
<!-- usual config stuff omitted -->
<membership defaultProvider="Mixed">
<providers>
<clear/>
<add name="Mixed"
type="Research.Web.Security.MixedMembershipProvider, Research.Web"
applicationName="/"
connectionStringName="ActiveDirectoryDefault"
sqlConnectionStringName="SqlDefault"
connectionUsername="mydomain\myadmin"
connectionPassword="mypass"/>
</providers>
</membership>
<!--- usual config stuff omitted -->
</system.web>
</configuration>
The above code will work for basic authentication, but you may need to override some of the other methods to handle password resets, lookups, etc. for the eventuality that an account is in SQL and not AD.