CodeAccessSecurityAttribute派生类抛出System.TypeLoadException(加载类型时发生失败)

时间:2016-04-05 13:56:44

标签: vb.net permissions code-access-security

我将自定义属性应用于CRUD存储库方法以控制访问:

Public Class SecureDbContextGenericRepository(Of TEntity As Class, TContext As DbContext)
  Inherits DbContextGenericRepository(Of TEntity, TContext)
  Public Sub New(connectionService As IConnectionService)
    MyBase.New(connectionService)
  End Sub
  <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
  Public Overrides Sub Delete(ParamArray entities() As TEntity)
    MyBase.Delete(entities)
  End Sub
  <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
  Public Overrides Sub Insert(ParamArray entities() As TEntity)
    MyBase.Insert(entities)
  End Sub
  <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataReader)>
  Public Overrides Function [Select](Optional predicate As Func(Of TEntity, Boolean) = Nothing) As IList(Of TEntity)
    Return MyBase.Select(predicate)
  End Function
  <EmployeeRoleRequirement(SecurityAction.Demand, EmployeeRoles:=EmployeeRoles.DataWriter)>
  Public Overrides Sub Update(ParamArray entities() As TEntity)
    MyBase.Update(entities)
  End Sub
End Class  

这是属性的实现:

Public Class EmployeeRoleRequirementAttribute
    Inherits CodeAccessSecurityAttribute
    Public Sub New(action As SecurityAction)
      MyBase.New(action)
    End Sub

    Public Overrides Function CreatePermission() As IPermission
      Return New EmployeeRolePermission(_EmployeeRoles)
    End Function

    Public Property EmployeeRoles As EmployeeRoles
  End Class  

<Flags>
  Public Enum EmployeeRoles As Integer
    DataReader = 0
    DataWriter = 1
  End Enum

许可:

Public Class EmployeeRolePermission
    Implements IPermission
    Public Sub New(employeeRoles As EmployeeRoles)
      _EmployeeRoles = employeeRoles
    End Sub

    Public Function Copy() As IPermission Implements IPermission.Copy
      Return New EmployeeRolePermission(_EmployeeRoles)
    End Function
    Public Sub Demand() Implements IPermission.Demand
      Dim principal = DirectCast(Thread.CurrentPrincipal, ProductionAssistantPrincipal)
      If Not principal.IsInRole(_EmployeeRoles) Then
        Throw New SecurityException(String.Format(My.Resources.EmployeeRoleNotFound,
                                                  principal.Identity.Name,
                                                  _EmployeeRoles.ToString()))
      End If
    End Sub
    Public Sub FromXml(e As SecurityElement) Implements ISecurityEncodable.FromXml
      Throw New NotImplementedException()
    End Sub
    Public Function Intersect(target As IPermission) As IPermission Implements IPermission.Intersect
      Return New EmployeeRolePermission(_EmployeeRoles And DirectCast(target, EmployeeRolePermission).EmployeeRoles)
    End Function
    Public Function IsSubsetOf(target As IPermission) As Boolean Implements IPermission.IsSubsetOf
      Return _EmployeeRoles.HasFlag(DirectCast(target, EmployeeRolePermission).EmployeeRoles)
    End Function
    Public Function ToXml() As SecurityElement Implements ISecurityEncodable.ToXml
      Throw New NotImplementedException()
    End Function
    Public Function Union(target As IPermission) As IPermission Implements IPermission.Union
      Return New EmployeeRolePermission(_EmployeeRoles Or DirectCast(target, EmployeeRolePermission).EmployeeRoles)
    End Function

    Public ReadOnly Property EmployeeRoles As EmployeeRoles
  End Class  

每次到达其中一个CRUD方法时,都会抛出TypeLoadException。我真的不知道原因,但如果我从CRUD方法中删除属性,一切正常。

2 个答案:

答案 0 :(得分:1)

这似乎是由于属性上的枚举值属性(有关详细信息,请参阅https://connect.microsoft.com/VisualStudio/feedback/details/596251/custom-cas-attributes-with-an-enum-property-set-cause-a-typeloadexception)。要解决此问题,可以在属性上使用字符串值属性,并在属性设置器中或在创建权限之前强制转换为枚举。 (就个人而言,我可能会选择前者,以便能够进行早期验证,但是ymmv ...)

答案 1 :(得分:0)

另一种解决方法是创建type的属性属性,该属性在Enum中使用,在本例中为Integer。

Public Class EmployeeRoleRequirementAttribute
  Inherits CodeAccessSecurityAttribute
  Public Sub New(action As SecurityAction)
    MyBase.New(action)
  End Sub
  Public Overrides Function CreatePermission() As IPermission
    Return New EmployeeRolePermission(CType(_RequiredEmployeeRoles, EmployeeRoles))
  End Function

  Public Property RequiredEmployeeRoles As Integer
End Class

<Flags>
Public Enum EmployeeRoles As Integer
  DataReader = 0
  DataWriter = 1
End Enum

然后你不需要使用String,它在使用属性时不允许轻松组合标志:

<EmployeeRoleRequirement(SecurityAction.Demand, RequiredEmployeeRoles:=EmployeeRoles.DataReader Or EmployeeRoles.DataWriter)>
Sub SecuredMethod()
End Sub