You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 23:00:55