0

我试图将我的应用程序锁定到用户和管理员可以看到整个控制器但只有管理员可以创建、删除和编辑的每种方法。

我创建了一个包含该方法的 CustomAuthorize 类:

 public class CustomAuthorize : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
            Debug.WriteLine("Show me the filterContext " + filterContext);
            if (filterContext.Result is HttpUnauthorizedResult)
            {
                Debug.WriteLine("Why is this going to the redirect to AccessDenied?");
                filterContext.Result = new RedirectResult("~/AccessDenied/Index");
            }
        }
    }

我的 RoleProvider 类:

namespace Office.WebUI.Security {
    public class OfficeRoleProvider : RoleProvider
    {

        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            throw new NotImplementedException();
        }

        public override string ApplicationName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override void CreateRole(string roleName)
        {
            throw new NotImplementedException();
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            throw new NotImplementedException();
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            throw new NotImplementedException();
        }

        public override string[] GetAllRoles()
        {
            throw new NotImplementedException();
        }

        public override string[] GetRolesForUser(string username)
        {
            Debug.WriteLine("Get the username" + username);
            using (EFDbContext db = new EFDbContext()) >           
            {
                User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, >stringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));
                //User user = db.TaskPrivilege.FirstOrDefault(u => >u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));

                if (user != null)
                {
                    var roles = from ur in user.UserRoles
                                from r in db.Roles
                                where user.role.RoleID == r.RoleID
                                //where ur.RoleID == r.RoleID
                                select r.Name;
                    if (roles != null)
                        return roles.ToArray();
                    else
                        return new string[] { }; ;
                }
                else
                {
                    return new string[] { }; ;
                }
            }
        }

        public override string[] GetUsersInRole(string roleName)
        {
           throw new NotImplementedException();
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            Debug.WriteLine("The username is " + username + " And the Role it is using is >" + roleName);
            using (EFDbContext db = new EFDbContext())
            {
                User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));

                if (user != null)
                {
                    var roles = from ur in user.UserRoles
                                from r in db.Roles
                                where user.role.RoleID == r.RoleID
                                //where ur.RoleID == r.RoleID
                                select r.Name;
                    if (user != null)
                        return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
                    else
                        return false;
                }
                else
                {
                    return false;
                }
            }
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            throw new NotImplementedException();
        }

        public override bool RoleExists(string roleName)
        {
            throw new NotImplementedException();
        }
    }

}

在我的数据库中,我有一个 Roles 表,其中包含 Role 和 RoleID 作为列,有 2 个值 Administrator 和 User 作为角色,roleID 作为 PK,1 = Administrator & 2 = User。另一个名为 Users 的表,其中包含 UserID、Username 和 role_RoleID

当我将用户分配给 role_RoleID 为 1(管理员)并使用锁定控制器时

[CustomAuthorize(角色 = "管理员"]

这行得通。

当我分配一个 role_RoldID = 2 并使用以下方法锁定时:

[CustomAuthorize(角色 = "用户"]

这不行吗?

另一个问题是,如何将 2 个角色分配给控制器?然后我想将每个方法锁定为 1 个用户角色。

希望这是有道理的,我希望有人可以帮助我。

谢谢

史蒂文

基本上我有一个控制器,我已经把 [CustomAuthorize(Roles = "Administrators, Support")] 它锁定了,所以两个角色都可以看到控制器。

然后我有创建/删除和编辑方法:

[CustomAuthorize(Roles = "Administrators")]

所以基本上我想向两个角色展示整个控制器,但只有管理员可以创建/编辑/删除。

当我在 user table = 2(User) 中分配一个 roleID 时,整个应用程序都会为该用户中断。分配 RoldID = 1(管理员)它适用于所有分配了 roldID 1 的人。

目前我有方法

public override string[] GetRolesForUser(string username)
{

    using (EFDbContext db = new EFDbContext())  

    {
        User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase) || u.Email.Equals(username, StringComparison.CurrentCultureIgnoreCase));


        if (user != null)
        {
            var roles = from ur in user.UserRoles
                        from r in db.Roles
                        where user.role.RoleID == r.RoleID

                        select r.Name;
            if (roles != null)
                return roles.ToArray();
            else
                return new string[] { }; ;
        }
        else
        {
            return new string[] { }; ;
        }
    }
}


> public override bool IsUserInRole(string username, string roleName)
>         {
>             
>             using (EFDbContext db = new EFDbContext())
>             {
>                 User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase)
> || u.Email.Equals(username,
> StringComparison.CurrentCultureIgnoreCase));
> 
>                 if (user != null)
>                 {
>                     var roles = from ur in user.UserRoles
>                                 from r in db.Roles
>                                 where user.role.RoleID == r.RoleID
>                                 //where ur.RoleID == r.RoleID
>                                 select r.Name;
>                     if (user != null)
>                         return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));
>                     else
>                         return false;
>                 }
>                 else
>                 {
>                     return false;
>                 }
>             }
>         }

我知道我必须更改 IsUserInRole 方法,以便它像这样处理数组参数,public override bool IsUserInRole(string username, string[] roleName)

但不知道如何在 linq 中处理它,主要是在 IsUserInRole 方法中:

return roles.Any(r => r.Equals(roleName, >StringComparison.CurrentCultureIgnoreCase));

目前它在 GetRolesForUser 方法上失败了,在我相信的 where 子句中,

其中 user.role.RoleID == r.RoleID

错误信息如下所示:

已经有一个与此命令关联的打开的 DataReader,必须先关闭它。说明:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.InvalidOperationException:已经有一个与此命令关联的打开的 DataReader,必须先关闭。

源错误:

第 66 行:var roles = 来自 user.UserRoles 中的 ur 第 67 行:来自 db.Roles 中的 r 第 68 行:其中 user.role.RoleID == r.RoleID

谢谢

4

1 回答 1

2

多个角色可以这样完成: [CustomAuthorize(Roles = "Administrator, User")] 但是看到你已经编写了这段代码,我想你已经知道了?

如果您只想Users避免进入您的创建/编辑/删除功能,为什么不使用默认的授权功能呢?意思是,把[CustomAuthorize(Roles = "Administrator")]编辑/创建/删除和[CustomAuthorize(Roles = "Administrator, User")]其他任何东西放在首位......

我猜是IsUserInRole被要求授权?此方法应采用 string[] roleName 数组,而不仅仅是字符串。

编辑:改变

                        var roles = from ur in user.UserRoles
                        from r in db.Roles
                       where user.role.RoleID == r.RoleID
                        //where ur.RoleID == r.RoleID
                       select r.Name;

var roles = user.UserRoles.select(q=>q.Roles.Name);
于 2012-11-13T09:50:50.987 回答