Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Tom 713 posts 954 karma points
    May 27, 2011 @ 04:31
    Tom
    0

    Active Directory BUG in 4.7

    Hi guys,

    when using a stock activedirectorymembership provider

    if you try and access a protected page you get you can override the call by implementing a custom provider but just wondering if you knew that bug existed.

    [ArgumentException: The parameter 'username' must not be empty.
    Parameter name: username]
       System.Web.Util.SecUtility.CheckParameter(String& param, Boolean checkForNull, Boolean checkIfEmpty, Boolean checkForCommas, Int32 maxSize, String paramName) +3909143
       System.Web.Security.ActiveDirectoryMembershipProvider.CheckUserName(String& username, Int32 maxSize, String paramName) +42
       System.Web.Security.ActiveDirectoryMembershipProvider.GetUser(String username, Boolean userIsOnline) +184
       System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline) +175
       umbraco.requestHandler..ctor(XmlDocument umbracoContent, String url) +3805
       umbraco.UmbracoDefault.Page_PreInit(Object sender, EventArgs e) +1294
       System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +25
       System.EventHandler.Invoke(Object sender, EventArgs e) +0
       System.Web.UI.Page.PerformPreInit() +49
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1700
    Unhandled Execution Error   
    The parameter 'username' must not be empty.
    Parameter name: username
      at System.Web.Util.SecUtility.CheckParameter(String& param, Boolean checkForNull, Boolean checkIfEmpty, Boolean checkForCommas, Int32 maxSize, String paramName)
      at System.Web.Security.ActiveDirectoryMembershipProvider.CheckUserName(String& username, Int32 maxSize, String paramName)
      at System.Web.Security.ActiveDirectoryMembershipProvider.GetUser(String username, Boolean userIsOnline)
      at System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline)
      at umbraco.requestHandler..ctor(XmlDocument umbracoContent, String url)
      at umbraco.UmbracoDefault.Page_PreInit(Object sender, EventArgs e)
      at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
      at System.EventHandler.Invoke(Object sender, EventArgs e)
      at System.Web.UI.Page.PerformPreInit()
      at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
  • Brian Powell 44 posts 199 karma points c-trib
    Jan 25, 2012 @ 21:14
    Brian Powell
    0

    I'm encountering the same problem with v4.7.1.  Can you explain more about what you did to work around this problem?

  • Tom 713 posts 954 karma points
    Jan 26, 2012 @ 23:15
    Tom
    0

    Hi Brian,

    I ended up implementing a custom membership provider and as well as this i used a custom role provider to cache my roles so the AD hit didn't take so long when calling stuff like IsProtected. The reason being every time you check if a node is protected umbraco tries to get all roles!

     

    public class CustomMembershipProvider : ActiveDirectoryMembershipProvider
        {
            public override MembershipUser GetUser(string username, bool userIsOnline)
            {
                if (!string.IsNullOrWhiteSpace(username))
                {
                    var result = (MembershipUser)HttpContext.Current.Session[username];
    
                    if (result == null || (string)HttpContext.Current.Session["recentUser"] != username)
                    {
                        result = base.GetUser(username, userIsOnline);
                        HttpContext.Current.Session[username] = result;
                        HttpContext.Current.Session["recentUser"] = username;
                    }
    
                    return result;
                }
                else
                {
                    return null;
                }
            }
    
            public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
            {
                return base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
            }
    
            public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
            {
                return base.FindUsersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords);
            }
    
            public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
            {
                return base.FindUsersByName(usernameToMatch, pageIndex, pageSize, out totalRecords);
            }
    
            public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
            {
                return base.GetAllUsers(pageIndex, pageSize, out totalRecords);
            }
    
            public override int GetNumberOfUsersOnline()
            {
                return base.GetNumberOfUsersOnline();
            }
    
            public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
            {
                return base.GetUser(providerUserKey, userIsOnline);
            }
    
            public override string GetUserNameByEmail(string email)
            {
                return base.GetUserNameByEmail(email);
            }
    
            public override bool ValidateUser(string username, string password)
            {
                return base.ValidateUser(username, password);
            }
        }
  • Tom 713 posts 954 karma points
    Jan 26, 2012 @ 23:17
    Tom
    0

    this was my web.config file:

      <membership defaultProvider="MyADMembershipProvider" userIsOnlineTimeWindow="15">

          <providers>

            <clear />

            <add name="MyADMembershipProvider" type="Project.Web.CustomMembershipProvider" connectionStringName="ADConnectionString" connectionUsername="someusername" connectionPassword="somepassword" connectionProtection="None" attributeMapUsername="SAMAccountName" enableSearchMethods="true" />

            <add name="MyADMembershipProvider" type="Project.Web.CustomMembershipProvider" connectionStringName="ADConnectionString" connectionUsername="someusername" connectionPassword="somepassword" connectionProtection="None" attributeMapUsername="SAMAccountName" enableSearchMethods="true" />

            <add name="UmbracoMembershipProvider" type="umbraco.providers.members.UmbracoMembershipProvider" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Another Type" passwordFormat="Hashed" />

            <add name="UsersMembershipProvider" type="umbraco.providers.UsersMembershipProvider" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />

          </providers>

        </membership>

        <!-- added by NH to support membership providers in access layer -->

        <roleManager enabled="true" defaultProvider="Custom_ActiveDirectoryRoleProvider">

          <providers>

            <clear />

            <add name="Custom_ActiveDirectoryRoleProvider" type="Project.Web.CustomRoleProvider" />

            <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />

            <add name="UmbracoRoleProvider" type="umbraco.providers.members.UmbracoRoleProvider" />

          </providers>

        </roleManager>

  • Brian Powell 44 posts 199 karma points c-trib
    Aug 28, 2012 @ 18:55
    Brian Powell
    0

    The root cause of this problem is that ActiveDirectoryMembershipProvider throws an ArgumentException when username is empty.  This occurs in umbraco.requesthandler.requestHandler() where it calls Membership.GetUser() and there is no currently logged in user.

    I was concerned about storing the user object in a session state variable and possible side effects.  The code I have checks if the username is null/whitespace/empty and returns null as Umbraco expects.  It also catches ArgumentException and returns null for Umbraco.  Otherwise, it calls ActiveDirectoryMembershipProvider.GetUser() without any caching.

     

    public override MembershipUser GetUser(string username, bool userIsOnline)
            {
                // If username is empty, whitespace or null, return null.  Will fail at base.GetUser() and avoids exception overhead.
                if (String.IsNullOrWhiteSpace(username))
                {
                    return null;
                }
     
                // If username is provided, try login.
                try
                {
                    return base.GetUser(username, userIsOnline);
                }
                catch (ArgumentException)
                {
                    // If ArgumentException is thrown, no user was logged in or username was incorrectly formatted.  Return null to conform to what Umbraco expects.
                    return null;
                }
            }
Please Sign in or register to post replies

Write your reply to:

Draft