views:

467

answers:

3

How do I tie up my custom membership provider with my ASP.NET MVC [Authorize()] attribute? I've blasted through a number of tutorials for how to create a custom membership provider but all the information I've found about how to hook it up to an application seems to revolve around regular ASP.NET WebForms applications which seem to be a piece of cake.

I'm coming unstuck with the amount of "magic" that just happens in ASP.NET MVC which is great, but I'm used to plugging stuff in in a WebForms way so this "it just works" methodology is a bit of a mind bender for me. How do I know when I'm supposed to do the heavy lifting or I'm supposed to just rely on it happening by magic?

Where do I tie my provider in to an MVC app? Am I right in assuming that it is invoked through the [Authorize()] attribute once I do get it hooked up?

A: 

How much did you change in this custom membership? Like did you change table names around? Can you log users in and stuff? Ie is your custom membership working?

If you changed lots of stuff around like you changed the roles table name to something different or stuff like that then your going to have to override the Authroize tag.

However if your custom membership is not working then you probably have not configured it right and configuring is the same as in webforms. You just have to setup your webconfig.

  </authentication>
    <membership>
      <providers>
        <clear />
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ConnectionString"
         enablePasswordRetrieval="false"
         enablePasswordReset="true"
          requiresQuestionAndAnswer="false"
          requiresUniqueEmail="true"
           passwordFormat="Hashed"
           maxInvalidPasswordAttempts="10"
           minRequiredPasswordLength="6"
           minRequiredNonalphanumericCharacters="0"
           passwordAttemptWindow="10"
           passwordStrengthRegularExpression=""
           applicationName="/"  />
      </providers>
    </membership>
    <profile>
      <providers>
        <clear />
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ConnectionString" applicationName="/" />
      </providers>
    </profile>
    <roleManager enabled="true">
      <providers>
        <clear />
        <add connectionStringName="ConnectionString"
          applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        <add applicationName="/" name="AspNetWindowsTokenRoleProvider"
          type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
      </providers>
    </roleManager>
chobo2
When you say - "what did we change around and stuff", we didn't change anything around, we're using an existing user database, not the one that the ASP.NET MVC wizard sets up for you... and to be honest, we have no intention of using the tutorial one, it's far more complex than necessary for our needs and doesn't meet the needs of our business model. So we've written a Membership Provider... the thing I'm clueless about is how does it hook my custom provider which I've specified in the web.config into my web application's codebase?
BobTheBuilder
Well everything I gave you is what you use to setup a custom database with a custom provider. Could you list the tables your using like are you using aspnet_UserInRoles? aspnet_user and any table that is prefixed with aspnet?
chobo2
+1  A: 

My custom membership provider is referenced in the web.config:

 <membership defaultProvider="MyMembershipProvider">
  <providers>
    <clear/>
    <add name="MyMembershipProvider" type="Namespace.MyMembershipProvider, Namespace" connectionStringName="connstring" [...] />
  </providers>
</membership>

Then just use static Membership class.

twk
Cool - what's to stop you specifying multiples in the web.config, and how where in my web application does it pull them into action?
BobTheBuilder
You're actually able to specify multiple membership providers. That's the reason you have to specify the defaultProvider. I feel like the utility of multiple providers is only seen in complex authorization mechanisms. But to get to a list the providers in code, you simple use the System.Web.Security.Membership.Providers property that returns a collection of membership providers specified in the web.cofig.
zowens
as zowens wrote.Actually, you can instantiate your own known provider just by normal MembershipProvider mp = new MyMembershipProvider();or by getting it from the list returned by Membership.Providers
twk
typically applications use only one membership provider, so the default one assigned to static Memebrship is a great shortcut.
twk
+3  A: 

Hopefully I can add some additional clarity over the other answers as they really don't explain what's going on which isn't going to help your confusion.

First up, implement your custom provider which from the sound of things you've done already, so I'll just throw up a little code snippet and won't go into any further detail here:

using System.Web.Security;

public class MyCustomMembershipProvider : MembershipProvider
{
    public override bool ValidateUser(string username, string password)
    {
        if (username.Equals("BenAlabaster") && password.Equals("Elephant"))
            return true;

        return false;
    }

    /* Override all the other methods required to extend MembershipProvider */        
}

Then you configure your provider in your web.config making sure to populate the attributes that configure the base MembershipProvider:

<membership defaultProvider="MyCustomMembershipProvider">      
    <providers>        
        <clear />        
        <add name="MyCustomMembershipProvider" 
             type="MyNamespace.MyCustomMembershipProvider" 
             enablePasswordRetrieval="false"
             enablePasswordReset="true"          
             requiresQuestionAndAnswer="false"          
             requiresUniqueEmail="true"           
             passwordFormat="Hashed"           
             maxInvalidPasswordAttempts="10"           
             minRequiredPasswordLength="6"           
             minRequiredNonalphanumericCharacters="0"           
             passwordAttemptWindow="10"           
             passwordStrengthRegularExpression=""           
             applicationName="/" />      
    </providers>     
</membership>

The next bit I think you're overthinking, the actual tie-in to your web application. Whereas in a WebForms app you kind of have to code the rest for yourself - the MVC framework does the rest for you - all you need to do is add the [Authorize] attribute to your action method and the framework will check to see if you're logged in, and if not redirect you to the login page. The login page will find your custom provider because that's what's configured in the web.config and will log your user in. You can access information about the logged in user from your controllers by referencing the User object:

public class WhateverController : Controller
{
    [Authorize]
    public ActionResult WhateverAction()
    {
        ViewData["LoggedInAs"] = string.Format("You are logged in as {0}.", User.Identity.Name);
        Return View();
    }
}

So this action requires that the user is logged in and presents the user information to the Whatever/WhateverAction.aspx view to be displayed on the page.

BenAlabaster
Okay, that makes sense - thanks for clearing that up. I just wasn't putting two and two together. I'm still stuck in that WebForms frame of mind and haven't figured out when MVC does it for me and when I've gotta handle it for myself.
BobTheBuilder