即使用户没有任何角色,GetRolesForUser也会返回所有角色

时间:2013-10-10 17:56:55

标签: asp.net-mvc

我在我的项目中使用SimpleRoleProvider但是在使用方法时

Roles.GetRolesForUser(用户名),即使用户没有任何角色,也会返回数据库中的所有角色。

这是一个已知的问题,有没有解决方法呢?

我想我可以手动访问usersInRoles,但是我需要这样做吗?

更新:

经过一番调查后,我发现当我不使用电子邮件地址时,它有效 用户名。

有没有人知道如何使用电子邮件地址作为用户名?

var username = GetUserNameById(id);
var test = Roles.GetRolesForUser(username);
var temp = test.Contains("Worker");
if (temp)

1 个答案:

答案 0 :(得分:0)

不幸的是,您提供的关于当前设置的信息非常少,所以我必须使用一些有根据的猜测。

您正在谈论SimpleRoleProvider,因此您很可能在WebMatrx.WebData中使用SimpleRoleProvider。 Sourcecode可以在Github上找到,所以我们来看看它:

    public override string[] GetRolesForUser(string username)
    {
        if (!InitializeCalled)
        {
            return PreviousProvider.GetRolesForUser(username);
        }
        using (var db = ConnectToDatabase())
        {
            int userId = SimpleMembershipProvider.GetUserId(db, SafeUserTableName, SafeUserNameColumn, SafeUserIdColumn, username);
            if (userId == -1)
            {
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, WebDataResources.Security_NoUserFound, username));
            }

            string query = @"SELECT r.RoleName FROM " + UsersInRoleTableName + " u, " + RoleTableName + " r Where (u.UserId = @0 and u.RoleId = r.RoleId) GROUP BY RoleName";
            return db.Query(query, new object[] { userId }).Select<dynamic, string>(d => (string)d[0]).ToArray();
        }
    }

正如我们所看到的,这个方法的第一件事就是通过SimpleMembershipProvider.GetUserId()获取所提供用户名的UserId,如下所示:

    // Not an override ==> Simple Membership MUST be enabled to use this method
    public int GetUserId(string userName)
    {
        VerifyInitialized();
        using (var db = ConnectToDatabase())
        {
            return GetUserId(db, SafeUserTableName, SafeUserNameColumn, SafeUserIdColumn, userName);
        }
    }

    internal static int GetUserId(IDatabase db, string userTableName, string userNameColumn, string userIdColumn, string userName)
    {
        var result = db.QueryValue(@"SELECT " + userIdColumn + " FROM " + userTableName + " WHERE (UPPER(" + userNameColumn + ") = @0)", userName.ToUpperInvariant());
        if (result != null)
        {
            return (int)result;
        }
        return -1;
    }

这里变得有趣了;在原作者构造SQL查询的行中,他正在做一些特殊的事情。他比较了大写形式的用户名(因为您可能将数据库设置为与区分大小写的排序规则,并且您的用户将自己注册为“David”并且现在正尝试登录为“david”,这只适用于案例 - 不敏感的整理)但是犯了一个错误。在右手边他正在使用username.ToUpperInvariant(),因为他知道Turkey Test,并且知道他应该以文化不敏感的形式比较他的弦乐,但在左手边他完全错过了它并使用TSQL的UPPER()函数,它使用您的数据库归类。

根据您选择的用户名,数据库排序规则和UserTable SimpleMembershipProvider.GetUserId()中的其他用户名仍会返回UserId,但这是错误的。

请直接致电SimpleMembershipProvider.GetUserId()来检查是否属于这种情况,如果我的猜测是正确的,您有两种选择

  1. 将用户名列的排序规则更改为 Latin1_General_CI_AI
  2. 根据IRoleProvider创建您自己的SimpleRoleProvider并使用适用于您的数据库归类的版本覆盖.GetUserId()