当认证公共一把umbraco访问错误 [英] umbraco public access error when authenticated

查看:265
本文介绍了当认证公共一把umbraco访问错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一把umbraco 7.

I have an issue with public access in Umbraco 7.

我使用自定义的成员提供我的CRM数据库的用户进行身份验证。
我定了一个规矩,让访问的认证(前端),用户只,我用一个自定义的角色提供定义身份验证的用户有游客的作用。如果不进行身份验证,他们将被重定向到登录页面。

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

当我调试的网站用户具有角色:

When I debug the website the user has the role :

我身份验证,并为当前用户的角色是不错的。

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

但我仍然重定向到登录页面!我不明白。

But I am still redirected to the login page ! I don't understand.

我的角色提供:

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);
        }
    }
}

下面是我用控制器的验证

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和参观者的角色被检测为在管理面板中的作用。

My role provider is in the web.config and the Visitors role is detected as role in the administration panel.

<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>

编辑:我忘记了成员资格提供程序:

I forgot the membership provider :

 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);
    }


}

每次我尝试访问具有特定的访问我重定向到即使我验证的登录页面的页面:

Every time I try to access a page that has specific access I get redirected to the login page even if I am authenticated:

我该如何解决呢?

推荐答案

你为什么要添加自定义角色提供。只要保持简单。如果你有一个注册页面的网站,你可以通过编程方式分配成员的类型和成员角色

Why do you want to add custom role provider. Just keep it simple. If you have a registration page for the site you can assign member type and member role programmatically

如果你从后台添加成员,您可以轻松地添加参观者的角色。

And if you add member from backend, you can add "Visitor" role easily.

因此​​,在这两种情况下,游客的角色,可以很容易地应用到所有成员,你可以保持您的网页背后登录访问者角色(所有认证)很容易。

So in both cases "Visitor" role can be applied easily to all members and you can keep your page behind login for visitor role(all authenticated) easily.

编辑:
我已删除添加角色到用户编程的,并不需要你和解决方案的code是如下:

I have removed the code of adding role to user programmatically as that is not needed by you and solution is as below:

正如你所知道的自定义角色提供程序和自定义成员资格提供齐头并进。您已经添加了自定义成员资格提供程序和overrided 的ValidateUser 方法,但对于这一切工作,你需要重写两个方法的getUser 见如下code定制供应商,它的工作

As you know for custom role provider and custom membership provider go hand in hand. You have added the custom membership provider and overrided ValidateUser method, but for all this to work you need to override two more methods of GetUser See the code for custom provider as below and it would work

的MembershipProvider

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 code的每一位,当用户试图访问受保护的页面,第一个的getUser(用户名字符串,布尔userIsOnline)在用户登录后被调用,如果失败,返回登录页面,在此之后是成功的的getUser(对象providerUserKey,布尔userIsOnline)收到电话。如果返回null,则没有足够的访问页显示其他 GetRolesForUser(用户名字符串)被调用。并呼吁所有的成功显示的页面。我已经设定这两个文件的每个方法破发点,所以只有这3种方法都参与其中。正如你看到的登录页面,我的猜测是的getUser(用户名字符串,布尔userIsOnline)这首调用失败的地方。

Okay, I have debugged every bit of code in roleprovider and membershipprovider, after the user is logged in when user tries to access protected page, first GetUser(string username, bool userIsOnline) gets called which, if failed, returns login page, after this is success GetUser(object providerUserKey, bool userIsOnline) gets a call. If this returns null, Insufficient access page is shown else GetRolesForUser(string username) gets called. and upon all success page is shown. I have set break point on each method of both files, so only these 3 methods are involved. as you see login page, my guess is GetUser(string username, bool userIsOnline) this first call is failing somewhere.

下面是我的文件,如果有帮助

Below are my files if it helps

角色配置的一部分。

<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

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

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配置

I reproduced your scenario, it is related to web.config configuration

当我不停的web配置为成员如下它没有击中我的供应商,除非我叫

when I kept web config for membership as below it did not hit my provider unless i called

<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>

但是,当改变为下面给出它的工作。请检查仔细配置的差异。

But when changed it to as given below it worked. please check the difference in config carefully.

<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 只。当我留了不同随后也出现了错误。

I think umbraco only takes one provider for members as well as users. Also when its name should be UmbracoMembershipProvider only. when I kept that different then also there was error.

这篇关于当认证公共一把umbraco访问错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆