.NET中基于角色GUID列表过滤权限列表结果异常求助
VB.NET角色权限过滤结果不符合预期问题排查
问题描述
原本习惯用SQL实现列表过滤,现在需要在.NET中完成以下需求:存在Role列表,每个角色对应页面级权限;用户属于若干角色,需以此为筛选条件过滤出用户拥有的页面权限。当前VB.NET代码中FilteredList返回3条数据,但预期应为2条。
相关代码
Partial Class TestUsers Inherits System.Web.UI.Page Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load Roles.Role = New List(Of Role) Roles.Role.Add(New Role(New Guid("EAC49E8F-BF55-44FD-BE69-5BBF7B5F289A"), "Admin", 0)) Roles.Role.Add(New Role(New Guid("A174A3ED-17F8-4450-9B25-3D2A21FCDDFF"), "User", 0)) Roles.Role.Add(New Role(New Guid("5780C40C-111A-4B4D-AA20-80E944B6B67A"), "Anon", 0)) Roles.Role.Add(New Role(New Guid("7E1DC89C-4B9C-49F8-9A37-0FA22A7C8116"), "HR", 0)) Dim UserPermission As New List(Of Role) UserPermission.Add(Roles.GetRoleByID(New Guid("EAC49E8F-BF55-44FD-BE69-5BBF7B5F289A"))) UserPermission.Add(Roles.GetRoleByID(New Guid("A174A3ED-17F8-4450-9B25-3D2A21FCDDFF"))) Dim PagePermission = RolePermission.GetPermissionFromString("Admin:1,1,1;User:1,0,0;Data:1,0,0;") Dim FilteredList = PagePermission.Where(Function(i) UserPermission.Contains(i.Role)).ToList Response.Write(FilteredList(0).Role.RoleName) Response.Write(UserPermission.Count()) Response.Write("<br>") Response.Write(PagePermission.Count()) Response.Write("<br>") Response.Write(FilteredList.Count()) End Sub Public Class RolePermission Public Role As Role Public Read As Boolean Public Edit As Boolean Public Admin As Boolean Public Sub New(Role As Role, Read As String, Edit As String, Admin As String) Me.Role = Role Me.Read = Read Me.Edit = Edit Me.Admin = Admin End Sub Public Shared Function GetPermissionFromString(Permission As String) As List(Of RolePermission) Dim u As New List(Of RolePermission) If Permission = "" Then Permission = "Anon:0,0,0;" Dim l As String() = Permission.TrimEnd(";").Split(";") For Each s In l If Not IsNothing(s.Split(":")) Then u.Add(New RolePermission(Roles.GetRoleByName(DbStr(Permission.Split(":")(0))), s.Split(":")(1).Split(",")(0), s.Split(":")(1).Split(",")(1), s.Split(":")(1).Split(",")(2))) End If Next Return u End Function End Class Public Class Role Public RoleID As Guid Public RoleName As String Public SiteGroupID As Integer Public Sub New(RoleID As Guid, RoleName As String, SiteGroupID As Integer) Me.RoleID = RoleID Me.RoleName = RoleName Me.SiteGroupID = SiteGroupID End Sub End Class Public Class Roles Public Shared Role As List(Of Role) Public Shared Function GetRoleByID(RoleID As Guid) As Role Return Role.Find(Function(s) s.RoleID = RoleID) End Function Public Shared Function GetRoleByName(RoleName As String) As Role Return Role.Find(Function(s) s.RoleName = RoleName) End Function End Class End Class
问题根源
1. GetPermissionFromString方法的字符串分割错误
在循环处理每个权限项时,代码错误地使用整个Permission字符串进行分割,而非当前循环的s项:
Roles.GetRoleByName(DbStr(Permission.Split(":")(0)))
这会导致无论循环到哪个权限项(Admin/User/Data),都只会取到第一个权限项的角色名"Admin",最终PagePermission中的三个RolePermission对象的Role属性都指向Admin角色。而用户权限列表UserPermission包含Admin角色,因此过滤时三个项都符合条件,返回3条数据。
2. (潜在问题)Role类未重写相等比较逻辑
List.Contains默认使用引用相等性比较,当前代码中UserPermission和PagePermission的Role实例来自同一个共享列表,所以引用一致不会出问题,但如果后续角色实例来自不同来源(比如数据库查询),会导致比较失效。
修复方案
1. 修正字符串分割错误
将GetPermissionFromString中的Permission.Split(":")(0)替换为s.Split(":")(0),同时增加数组长度检查避免越界:
Public Shared Function GetPermissionFromString(Permission As String) As List(Of RolePermission) Dim u As New List(Of RolePermission) If Permission = "" Then Permission = "Anon:0,0,0;" Dim l As String() = Permission.TrimEnd(";").Split(";") For Each s In l Dim roleParts = s.Split(":") If roleParts.Length = 2 Then Dim permParts = roleParts(1).Split(",") If permParts.Length = 3 Then u.Add(New RolePermission(Roles.GetRoleByName(DbStr(roleParts(0))), permParts(0), permParts(1), permParts(2))) End If End If Next Return u End Function
2. (可选)重写Role类的相等比较方法
为Role类重写Equals和GetHashCode,基于RoleID进行相等性判断,确保即使实例引用不同,只要RoleID一致就会被判定为相等:
Public Class Role Public RoleID As Guid Public RoleName As String Public SiteGroupID As Integer Public Sub New(RoleID As Guid, RoleName As String, SiteGroupID As Integer) Me.RoleID = RoleID Me.RoleName = RoleName Me.SiteGroupID = SiteGroupID End Sub Public Overrides Function Equals(obj As Object) As Boolean If obj Is Nothing OrElse Not TypeOf obj Is Role Then Return False End If Return DirectCast(obj, Role).RoleID = Me.RoleID End Function Public Overrides Function GetHashCode() As Integer Return RoleID.GetHashCode() End Function End Class
内容的提问来源于stack exchange,提问作者Gavin Clayton
相关产品推荐
相关产品推荐

