Umbraco public access error during authentication

I have an open access issue in Umbraco 7.

I use a custom membership provider to authenticate users through my CRM database. I set a rule to access only authenticated (front-end) users , and I used a custom role provider to identify authenticated users, the visitors role. If they are not authenticated, they are redirected to the login page.

public access

When I debug a site, the user has a role:

Role test

I am authenticated and the role for the current user is good.

Role test

But I'm still redirected to the login page! I do not understand.

My role provider:

public class CustomRoleProvider : Umbraco.Web.Security.Providers.MembersRoleProvider
{
    const int SITE_ID = 6;

    public override string ApplicationName
    {
        get
        {
            return "Site";
        }
    }

    public override string[] GetAllRoles()
    {
        return new[] { Const.VISITORS_LABEL };
    }

    public override string[] GetRolesForUser(string username)
    {
        return new[] { Const.VISITORS_LABEL };
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="username"></param>
    /// <param name="roleName"></param>
    /// <returns></returns>
    public override bool IsUserInRole(string username, string roleName)
    {
        //every user is a visitor
        if(roleName == Const.VISITORS_LABEL)
        {
            return true;
        }

        else
        {
            return base.IsUserInRole(username, roleName);
        }
    }

    public override string[] GetUsersInRole(string roleName)
    {
        if(roleName == Const.VISITORS_LABEL)
        {
            using (var db = new CRMEntities())
            {
                var usersEmails = db.Customer_View.Where(x => x.SiteID == SITE_ID).Select(x=>x.Email).ToArray();
                return usersEmails;
            }
        }
        else
        {
            return base.GetUsersInRole(roleName);
        }
    }
}

Here is the controller that I use for authentication :

public class MemberLoginSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
    // The MemberLogin Action returns the view, which we will create later. It also instantiates a new, empty model for our view:

    [HttpGet]
    [ActionName("MemberLogin")]
    public ActionResult MemberLoginGet()
    {
        return PartialView("MemberLogin", new MemberLoginModel());
    }

    // The MemberLogout Action signs out the user and redirects to the site home page:

    [HttpGet]
    public ActionResult MemberLogout()
    {
        Session.Clear();
        FormsAuthentication.SignOut();
        return Redirect("/");
    }

    // The MemberLoginPost Action checks the entered credentials using the standard Asp Net membership provider and redirects the user to the same page. Either as logged in, or with a message set in the TempData dictionary:
    [HttpPost]
    [ActionName("MemberLogin")]
    public ActionResult MemberLoginPost(MemberLoginModel model)
    {
        if (Membership.ValidateUser(model.Username, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);

            return RedirectToCurrentUmbracoPage();
        }

        else
        {
            TempData["Status"] = "Invalid username or password";
            return RedirectToCurrentUmbracoPage();
        }
    }
}

web.config, .

<roleManager enabled="true" defaultProvider="CustomRoleProvider">
  <providers>
    <clear />
    <add name="UmbracoRoleProvider" type="Umbraco.Web.Security.Providers.MembersRoleProvider" />
    <add name="CustomRoleProvider" type="*.UI.Helpers.CustomRoleProvider" />
  </providers>
</roleManager>

EDIT: :

 public class MyMembershipProvider : Umbraco.Web.Security.Providers.MembersMembershipProvider
{

const int SITE_ID = 6;
    //we dont let user change their password using RC website
    public override bool AllowManuallyChangingPassword
    {
        get
        {
            return false;
        }
    }

    public override bool EnablePasswordReset
    {
        get
        {
            return false;
        }
    }

    public override bool EnablePasswordRetrieval
    {
        get
        {
            return false;
        }
    }

    public override bool ValidateUser(string username, string password)
    {
        Customer_View user;

        //just to avoid errors with uppercase letters
        username = username.ToLowerInvariant();

        using (var db = new CRMEntities())
        {
            user = db.Customer_View.SingleOrDefault(x => x.Email == username && x.SiteID == SITE_ID);

            //no user with this email
            if (user == null)
                return false;

            //check if password is same
            return user.Password == password;
        }
    }

    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        //just to avoid errors with uppercase letters
        username = username.ToLowerInvariant();
        MembershipUser toReturn;

        using (var db = new CRMEntities())
        {
            Customer_View user = db.Customer_View.SingleOrDefault(x => x.Email == username && x.SiteID == SITE_ID);

            toReturn = user != null ? new MembershipUser(
                //provider name
                "MyMembershipProvider", string.Format("{0} {1}", user.FirstName, user.LastName),
                username, username, string.Empty, string.Empty, true, true, user.CreateDate, new DateTime(), new DateTime(), new DateTime(), new DateTime()) :

                null;

        }

        return toReturn;
    }

    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    {
        return this.GetUser(providerUserKey as string, userIsOnline);
    }


}

, , , :

login page

?

+4
2

. . ,

, "".

, "" , ( ).

EDIT: , , :

, . ValidateUser, GetUser . , ,

MembershipProvider

public class MyMembershipProvider : MembersMembershipProvider
{
    public override bool ValidateUser(string username, string password)
    {
        if (base.ValidateUser(username,password))
        {
            //if this is umbraco user validate by base method
            return true;
        }
        else
        {
            var allow = //add your validation code for CRM, I have checked if username is "tester" and allowed for testing purpose.
            return allow;
        }
    }
    // These two methods below which you have not overridden and need to override for public access to work

    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    {
        if(base.GetUser(providerUserKey, false)!=null)
            //if this is umbraco user add it as is.
            return base.GetUser(providerUserKey,userIsOnline);
        else
            //Add your CRM user, I do not have database, so added test user
            return new MembershipUser("UmbracoMembershipProvider", "tester", 1233, "tester@test.com", null, null, true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
    }
    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        if (true)//check if this is CRM user here
        {
            return new MembershipUser("UmbracoMembershipProvider", "tester", 1233, "tester@test.com", null, null, true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
            //I am adding test user, you should create user from your CRM database
        }
        else
            return base.GetUser(username,false);

    }

}

EDIT2

, roleprovider membershipprovider , , , GetUser(string username, bool userIsOnline), , , , GetUser(object providerUserKey, bool userIsOnline) . null, " " else else GetRolesForUser(string username). . , 3 . , GetUser(string username, bool userIsOnline), - .

,

config part

<roleManager enabled="true" defaultProvider="UmbracoRoleProvider">
  <providers>
    <clear />
    <!--<add name="UmbracoRoleProvider" type="Umbraco.Web.Security.Providers.MembersRoleProvider" />-->
    <add name="UmbracoRoleProvider" type="Assembly.Providers.MyRolesProvider" />
  </providers>
</roleManager>

<membership defaultProvider="UmbracoMembershipProvider" userIsOnlineTimeWindow="15">
  <providers>
    <clear />
    <add name="UmbracoMembershipProvider" type="Assembly.Providers.MyMemberShipProvider, Assembly" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Member" passwordFormat="Hashed" />
    <!--<add name="UsersMembershipProvider" type="Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="4" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />-->
    <add name="UsersMembershipProvider" type="Assembly.Providers.MyUserMembershipProvider, Assembly" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="4" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />
  </providers>
</membership>

AccountController

public class AccountSurfaceController : Umbraco.Web.Mvc.SurfaceController
{
    [HttpPost]
    public ActionResult LoginForm(LoginModel model)
    {
        //model not valid, do not save, but return current umbraco page
        if (!ModelState.IsValid)
        {
            //Perhaps you might want to add a custom message to the TempData or ViewBag
            //which will be available on the View when it renders (since we're not 
            //redirecting)          
            return CurrentUmbracoPage();
        }

        // Login
        if (Membership.ValidateUser(model.Username, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.Username, false);
            return RedirectToCurrentUmbracoUrl();
        }
        else
        {
            ModelState.AddModelError("Username", "Username is not valid");
            return CurrentUmbracoPage();
        }
    }
}

public class LoginModel
{
    [Required]
    public string Username { get; set; }

    [Required]
    [DataType(DataType.Password)] 
    public string Password { get; set; }
}

RolesProvider

public class MyRolesProvider : MembersRoleProvider
{
    const string VISITORS_LABEL = "Visitor";

    public override string[] GetAllRoles()
    {
        var roles = base.GetAllRoles().ToList();
        roles.Add(VISITORS_LABEL);
        return roles.ToArray();
    }
    public override string[] FindUsersInRole(string roleName, string usernameToMatch)
    {
        if(roleName== VISITORS_LABEL)
        {
            var users = ApplicationContext.Current.Services.MemberService
                .GetAllMembers().Select(m => m.Email).ToList();
            users.Add("tester@test.com");
            return users.ToArray();
        }
        return base.FindUsersInRole(roleName, usernameToMatch);
    }
    public override bool RoleExists(string roleName)
    {
        if(roleName == VISITORS_LABEL)
        {
            return true;
        }
        return base.RoleExists(roleName);
    }
    public override string[] GetRolesForUser(string username)
    {
        var roles = base.GetRolesForUser(username).ToList();
        roles.Add(VISITORS_LABEL);
        return roles.ToArray();
    }
    public override bool IsUserInRole(string username, string roleName)
    {
        if(roleName == VISITORS_LABEL)
        {
            return true;
        }
        return base.IsUserInRole(username, roleName);
    }
    public override string[] GetUsersInRole(string roleName)
    {
        if(roleName == VISITORS_LABEL)
        {
            var list = ApplicationContext.Current.Services.MemberService
                .GetAllMembers().Select(m => m.Email).ToList();
                list.Add("tester@test.com");
            return list.ToArray();
        }
        return base.GetUsersInRole(roleName);
    }
}

EDIT3:

, web.config

- , , ,

<membership defaultProvider="MyMembershipProvider" userIsOnlineTimeWindow="15">
  <providers>
    <clear />
    <add name="UmbracoMembershipProvider" type="Umbraco.Web.Security.Providers.MembersMembershipProvider, Umbraco" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="4" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Member" passwordFormat="Hashed" />
    <add name="MyMembershipProvider" type="Umbraco724.Providers.MyMembersMembershipProvider, Umbraco724" />
    <add name="UsersMembershipProvider" type="Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="4" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />
  </providers>
</membership>

, , . , .

<membership defaultProvider="UmbracoMembershipProvider" userIsOnlineTimeWindow="15">
  <providers>
    <clear />
    <add name="UmbracoMembershipProvider" type="Umbraco724.Providers.MyMembersMembershipProvider, Umbraco724"  minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="4" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Visitor" passwordFormat="Hashed" />
    <add name="UsersMembershipProvider" type="Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="4" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />
  </providers>
</membership>

, umbraco , . , UmbracoMembershipProvider. -, .

+2

Umbraco, , , ​​ . URL- , .

RedirectToCurrentUmbracoPage() , URL- . , , - URL. , RedirectToCurrentUmbracoPage() MemberLoginPost RedirectToCurrentUmbracoUrl().

RedirectToCurrentUmbracoPage(), , . CurrentUmbracoPage() , . . :

[HttpPost]
[ActionName("MemberLogin")]
public ActionResult MemberLoginPost(MemberLoginModel model)
{
    if (Membership.ValidateUser(model.Username, model.Password))
    {
        FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);

        return RedirectToCurrentUmbracoUrl();
    }

    else
    {
        TempData["Status"] = "Invalid username or password";

        return CurrentUmbracoPage();
    }
}
0

All Articles