CA2119: Impostare come sealed i metodi che soddisfano interfacce private
TypeName |
SealMethodsThatSatisfyPrivateInterfaces |
CheckId |
CA2119 |
Category |
Microsoft.Security |
Breaking Change |
Breaking |
Causa
Un tipo pubblico ereditabile fornisce un'implementazione di metodo sottoponibile a override di un'interfaccia internal (Friend in Visual Basic).
Descrizione della regola
I metodi dell'interfaccia dispongono di accessibilità pubblica, che non è possibile modificare mediante il tipo di implementazione.Un'interfaccia interna crea un contratto di cui non è prevista l'implementazione all'esterno dell'assembly che definisce l'interfaccia.Un tipo pubblico che implementa un metodo di un'interfaccia interna mediante il modificatore virtual (Overridable in Visual Basic) consente di eseguire l'override del metodo con un tipo derivato che si trova all'esterno dell'assembly.Se un secondo tipo nell'assembly di definizione chiama il metodo e prevede un contratto solo interno, è possibile che il comportamento risulti compromesso quando il metodo sottoposto a override nell'assembly esterno viene invece eseguito.In tal modo viene creata una vulnerabilità della sicurezza.
Come correggere le violazioni
Per correggere una violazione di questa regola, impedire che venga eseguito l'override del metodo esternamente all'assembly utilizzando una delle soluzioni illustrate di seguito:
Rendere sealed (NotInheritable in Visual Basic) il tipo di dichiarazione.
Modificare l'accessibilità del tipo di dichiarazione in internal (Friend in Visual Basic).
Rimuovere tutti i costruttori pubblici dal tipo di dichiarazione.
Implementare il metodo senza utilizzare il modificatore virtual.
Implementare il metodo in maniera esplicita.
Esclusione di avvisi
È sicuro escludere un avviso da questa regola se dopo un attento esame risulterà che non potranno derivare problemi di sicurezza se verrà eseguito l'override del metodo esterno all'assembly.
Esempio
Nell'esempio riportato di seguito viene illustrato un tipo, BaseImplementation, che viola questa regola.
Imports System
Namespace SecurityLibrary
Interface IValidate
Function UserIsValidated() As Boolean
End Interface
Public Class BaseImplementation
Implements IValidate
Overridable Function UserIsValidated() As Boolean _
Implements IValidate.UserIsValidated
Return False
End Function
End Class
Public Class UseBaseImplementation
Sub SecurityDecision(someImplementation As BaseImplementation)
If(someImplementation.UserIsValidated() = True)
Console.WriteLine("Account number & balance.")
Else
Console.WriteLine("Please login.")
End If
End Sub
End Class
End Namespace
using System;
namespace SecurityLibrary
{
// Internal by default.
interface IValidate
{
bool UserIsValidated();
}
public class BaseImplementation : IValidate
{
public virtual bool UserIsValidated()
{
return false;
}
}
public class UseBaseImplementation
{
public void SecurityDecision(BaseImplementation someImplementation)
{
if(someImplementation.UserIsValidated() == true)
{
Console.WriteLine("Account number & balance.");
}
else
{
Console.WriteLine("Please login.");
}
}
}
}
using namespace System;
namespace SecurityLibrary
{
// Internal by default.
interface class IValidate
{
bool UserIsValidated();
};
public ref class BaseImplementation : public IValidate
{
public:
virtual bool UserIsValidated()
{
return false;
}
};
public ref class UseBaseImplementation
{
public:
void SecurityDecision(BaseImplementation^ someImplementation)
{
if(someImplementation->UserIsValidated() == true)
{
Console::WriteLine("Account number & balance.");
}
else
{
Console::WriteLine("Please login.");
}
}
};
}
Nell'esempio seguente viene utilizzata l'implementazione del metodo virtuale dell'esempio precedente:
Imports System
Namespace SecurityLibrary
Public Class BaseImplementation
Overridable Function UserIsValidated() As Boolean
Return False
End Function
End Class
Public Class UseBaseImplementation
Sub SecurityDecision(someImplementation As BaseImplementation)
If(someImplementation.UserIsValidated() = True)
Console.WriteLine("Account number & balance.")
Else
Console.WriteLine("Please login.")
End If
End Sub
End Class
End Namespace
using System;
namespace SecurityLibrary
{
public class BaseImplementation
{
public virtual bool UserIsValidated()
{
return false;
}
}
public class UseBaseImplementation
{
public void SecurityDecision(BaseImplementation someImplementation)
{
if (someImplementation.UserIsValidated() == true)
{
Console.WriteLine("Account number & balance.");
}
else
{
Console.WriteLine("Please login.");
}
}
}
}
using namespace System;
namespace SecurityLibrary
{
public ref class BaseImplementation
{
public:
virtual bool UserIsValidated()
{
return false;
}
};
public ref class UseBaseImplementation
{
public:
void SecurityDecision(BaseImplementation^ someImplementation)
{
if(someImplementation->UserIsValidated() == true)
{
Console::WriteLine("Account number & balance.");
}
else
{
Console::WriteLine("Please login.");
}
}
};
}
Vedere anche
Riferimenti
Interfacce (Guida per programmatori C#)