Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which Membership Provider implements users stored in web.config?

Having a code-blind moment.

ASP.NET 4.0.

Web.config:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <authentication mode="Forms">
      <forms name="DataViewer" loginUrl="login.aspx">
        <credentials passwordFormat="Clear">
          <user name="devuser" password="test" />
        </credentials>
      </forms>
    </authentication>
    <authorization>
      <deny users="?" />
    </authorization>
  </system.web>

and a login control:

  <asp:Login ID="login" runat="server" />

If I enter a username and password, and click Login, it hangs.

If I break, I can see in the call stack that login.AuthenticateUsingMembershipProvider() is in the middle of calling SqlMembershipProvider.ValidateUser(). There is no database defined or involved in this project at all, and I haven't specified that SqlMembershipProvider should be used.

So my question is, what membership provider should I use to get ASP.NET to use the usernames and passwords in the <credentials> element of web.config?

like image 663
tomfanning Avatar asked Sep 14 '12 13:09

tomfanning


2 Answers

I'm amazed that considering how the framework designers went to the trouble of defining a <credentials /> element that they didn't implement any code to consume it.

I found a sort-of-working implementation of this here which I have fixed up and included below. All other members of MembershipProvider throw NotImplementedException.

using System.Configuration;
using System.Web.Configuration;
using System.Web.Security;

public class WebConfigMembershipProvider : MembershipProvider
{
    private FormsAuthenticationUserCollection _users = null;
    private FormsAuthPasswordFormat _passwordFormat;

    public override void Initialize(string name,
      System.Collections.Specialized.NameValueCollection config)
    {
        base.Initialize(name, config);
        _passwordFormat = getPasswordFormat();
    }

    public override bool ValidateUser(string username, string password)
    {
        var user = getUsers()[username];
        if (user == null) return false;

        if (_passwordFormat == FormsAuthPasswordFormat.Clear)
        {
            if (user.Password == password)
            {
                return true;
            }
        }
        else
        {
            if (user.Password == FormsAuthentication.HashPasswordForStoringInConfigFile(password,
                _passwordFormat.ToString()))
            {
                return true;
            }
        }

        return false;
    }

    protected FormsAuthenticationUserCollection getUsers()
    {
        if (_users == null)
        {
            AuthenticationSection section = getAuthenticationSection();
            FormsAuthenticationCredentials creds = section.Forms.Credentials;
            _users = section.Forms.Credentials.Users;
        }
        return _users;
    }

    protected AuthenticationSection getAuthenticationSection()
    {
        Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
        return (AuthenticationSection)config.GetSection("system.web/authentication");
    }

    protected FormsAuthPasswordFormat getPasswordFormat()
    {
        return getAuthenticationSection().Forms.Credentials.PasswordFormat;
    }
}
like image 196
tomfanning Avatar answered Oct 23 '22 04:10

tomfanning


You are going to need to write your own provider for this. It should be relatively straightforward to take the sample ReadOnlyXmlMembershipProvider in the MSDN documentation and change it to read users and credentials from web.config, instead of an external XML file.

like image 40
StuartLC Avatar answered Oct 23 '22 03:10

StuartLC