views:

186

answers:

1

I have a task of dealing with security on my .Net web application, the way it is to work is that if the user is logged in to Active Directory and the users AD name is in a database then they will be let in.

On the same bases if the users AD name is not in the database then they will be asked to login, with a user name and password, held in the database.

So I need some kind of mix mode security login using the Membership and Role provider.

Where I am having trouble is where do you detect if a user can login using AD, so they get logged in automatically.

+1  A: 

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.

HackedByChinese