मैं विरासत सुरक्षा नियमों का उल्लंघन किए बिना.NET 4+ में ISerializable कैसे लागू कर सकता हूं?




serialization .net-4.0 (3)

बैकग्राउंडर: नोदा टाइम में कई धारावाहिक संरचनाएँ होती हैं। जब मैं बाइनरी सीरियलाइजेशन को नापसंद करता हूं, तो हमें 1.x टाइमलाइन में वापस इसे सपोर्ट करने के लिए कई अनुरोध मिले। हम इसे ISerializable इंटरफ़ेस लागू करके समर्थन करते हैं।

हमें .NET फिडल के भीतर Noda Time 2.x में विफल रहने की हालिया समस्या रिपोर्ट मिली है। Noda Time 1.x का उपयोग करने वाला समान कोड ठीक काम करता है। अपवाद फेंक दिया गया है:

सदस्य को ओवरराइड करते समय इनहेरिटेंस सुरक्षा नियमों का उल्लंघन हुआ: 'NodaTime.Duration.Systemime.erialization.ISerializable.GetObjectData (System.Runtime.Serialization। ओवरराइडिंग विधि की सुरक्षा पहुंच क्षमता से अधिक होने की विधि की सुरक्षा पहुंच से मेल खाना चाहिए।

मैंने इसे उस रूपरेखा तक सीमित कर दिया है जो लक्षित है: 1.x लक्ष्य .NET 3.5 (ग्राहक प्रोफ़ाइल); 2.x लक्ष्य .NET 4.5। वे PCL बनाम .NET कोर और प्रोजेक्ट फ़ाइल संरचना के समर्थन में बड़े अंतर हैं, लेकिन ऐसा लगता है कि यह अप्रासंगिक है।

मैं इसे एक स्थानीय परियोजना में पुन: पेश करने में कामयाब रहा हूं, लेकिन मुझे इसका कोई हल नहीं मिला है।

VS2017 में प्रजनन के लिए कदम:

  • एक नया समाधान बनाएँ
  • .NET 4.5.1 को लक्षित करते हुए एक नया क्लासिक विंडोज कंसोल एप्लिकेशन बनाएं। मैंने इसे "कोडरनर" कहा।
  • परियोजना के गुणों में, साइनिंग पर जाएं और एक नई कुंजी के साथ विधानसभा पर हस्ताक्षर करें। पासवर्ड की आवश्यकता को अनटिक करें, और किसी भी कुंजी फ़ाइल नाम का उपयोग करें।
  • Program.cs को बदलने के लिए निम्न कोड चिपकाएँ। यह इस Microsoft नमूने में कोड का संक्षिप्त रूप है। मैंने सभी रास्तों को एक समान रखा है, इसलिए यदि आप फुलर कोड पर वापस जाना चाहते हैं, तो आपको कुछ और बदलने की आवश्यकता नहीं है।

कोड:

using System;
using System.Security;
using System.Security.Permissions;

class Sandboxer : MarshalByRefObject  
{  
    static void Main()  
    {  
        var adSetup = new AppDomainSetup();  
        adSetup.ApplicationBase = System.IO.Path.GetFullPath(@"..\..\..\UntrustedCode\bin\Debug");  
        var permSet = new PermissionSet(PermissionState.None);  
        permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));  
        var fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<System.Security.Policy.StrongName>();  
        var newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly);  
        var handle = Activator.CreateInstanceFrom(  
            newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,  
            typeof(Sandboxer).FullName  
            );  
        Sandboxer newDomainInstance = (Sandboxer) handle.Unwrap();  
        newDomainInstance.ExecuteUntrustedCode("UntrustedCode", "UntrustedCode.UntrustedClass", "IsFibonacci", new object[] { 45 });  
    }  

    public void ExecuteUntrustedCode(string assemblyName, string typeName, string entryPoint, Object[] parameters)  
    {  
        var target = System.Reflection.Assembly.Load(assemblyName).GetType(typeName).GetMethod(entryPoint);
        target.Invoke(null, parameters);
    }  
}
  • "अनट्रस्टेडकोड" नामक एक और प्रोजेक्ट बनाएं। यह एक क्लासिक डेस्कटॉप क्लास लाइब्रेरी प्रोजेक्ट होना चाहिए।
  • विधानसभा पर हस्ताक्षर; आप कोडरनर के लिए एक नई कुंजी या उसी का उपयोग कर सकते हैं। (यह आंशिक रूप से नोदा समय की स्थिति की नकल करने के लिए है, और आंशिक रूप से कोड विश्लेषण को खुश रखने के लिए है।)
  • Class1.cs में निम्नलिखित कोड पेस्ट करें (ओवरराइटिंग क्या है):

कोड:

using System;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;

// [assembly: AllowPartiallyTrustedCallers]

namespace UntrustedCode
{
    public class UntrustedClass
    {
        // Method named oddly (given the content) in order to allow MSDN
        // sample to run unchanged.
        public static bool IsFibonacci(int number)
        {
            Console.WriteLine(new CustomStruct());
            return true;
        }
    }

    [Serializable]
    public struct CustomStruct : ISerializable
    {
        private CustomStruct(SerializationInfo info, StreamingContext context) { }

        //[SecuritySafeCritical]
        //[SecurityCritical]
        //[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            throw new NotImplementedException();
        }
    }
}

कोडरनर प्रोजेक्ट चलाना निम्नलिखित अपवाद देता है (पठनीयता के लिए सुधारित):

अखंडित अपवाद: System.Reflection.TargetInvocationException:
एक आह्वान के लक्ष्य से अपवाद को फेंक दिया गया है।
--->
System.TypeLoadException:
सदस्य को ओवरराइड करते समय उल्लंघन सुरक्षा नियमों का उल्लंघन:
'UntrustedCode.CustomStruct.System.Runtime.Serialization.ISerializable.GetObjectData (...)।
ओवरराइडिंग विधि की सुरक्षा पहुंच सुरक्षा से मेल खाना चाहिए
विधि की पहुँच से वंचित होना।

टिप्पणी की गई विशेषताएँ उन चीज़ों को दिखाती हैं जिन्हें मैंने आज़माया है:

  • SecurityPermission को दो अलग-अलग MS लेखों ( first , second ) द्वारा अनुशंसित किया जाता है, हालांकि दिलचस्प रूप से वे स्पष्ट / अंतर्निहित इंटरफ़ेस के आसपास अलग-अलग चीजें करते हैं
  • SecurityCritical वह है जो वर्तमान में Noda Time में है, और इस प्रश्न का उत्तर क्या है
  • SecuritySafeCritical कुछ हद तक कोड विश्लेषण नियम संदेशों द्वारा सुझाया गया है
  • किसी भी विशेषता के बिना, कोड विश्लेषण नियम खुश हैं - या तो SecurityPermission या SecurityCritical वर्तमान के साथ, नियम आपको विशेषताओं को हटाने के लिए कहते हैं - जब तक कि आपके पास AllowPartiallyTrustedCallers । दोनों मामलों में सुझावों का पालन करने से कोई मदद नहीं मिलती है।
  • Noda Time ने AllowPartiallyTrustedCallers को AllowPartiallyTrustedCallers लागू किया है; यहाँ उदाहरण या तो लागू विशेषता के साथ या उसके बिना काम नहीं करता है।

यदि मैं [assembly: SecurityRules(SecurityRuleSet.Level1)] को AllowPartiallyTrustedCallers असेंबली में AllowPartiallyTrustedCallers (और AllowPartiallyTrustedCallers विशेषता को AllowPartiallyTrustedCallers है) तो कोड बिना किसी अपवाद के चलता है, लेकिन मेरा मानना ​​है कि समस्या का एक बुरा समाधान है जो अन्य कोड को बाधित कर सकता है।

मैं पूरी तरह से खो जाने की बात स्वीकार करता हूं जब यह .NET के सुरक्षा पहलू पर आता है। तो मैं .NET 4.5 को लक्षित करने के लिए क्या कर सकता हूं और फिर भी अपने प्रकारों को ISerializable को लागू करने की अनुमति देता हूं और अभी भी .NET Fiddle जैसे वातावरण में उपयोग किया जा सकता है?

(जब मैं .NET 4.5 को लक्षित कर रहा हूं, मेरा मानना ​​है कि यह .NET 4.0 सुरक्षा नीति में परिवर्तन है, जो इस समस्या का कारण है, इसलिए टैग।)


MSDN अनुसार देखें:

उल्लंघन कैसे ठीक करें?

इस नियम के उल्लंघन को ठीक करने के लिए, GetObjectData विधि को दृश्यमान और अधिक उपयोग योग्य बनायें और सुनिश्चित करें कि सभी उदाहरण फ़ील्ड क्रमबद्धता प्रक्रिया में शामिल हैं या स्पष्ट रूप से NonSerializedAttribute विशेषता के साथ चिह्नित हैं।

निम्न example पुस्तक श्रेणी पर ISerializable.GetObjectData का एक अधिशेष कार्यान्वयन प्रदान करके और पुस्तकालय वर्ग पर ISerializable.GetObjectData का कार्यान्वयन प्रदान करके पिछले दो उल्लंघनों को ठीक करता है।

using System;
using System.Security.Permissions;
using System.Runtime.Serialization;

namespace Samples2
{
    [Serializable]
    public class Book : ISerializable
    {
        private readonly string _Title;

        public Book(string title)
        {
            if (title == null)
                throw new ArgumentNullException("title");

            _Title = title;
        }

        protected Book(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            _Title = info.GetString("Title");
        }

        public string Title
        {
            get { return _Title; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Title", _Title);
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            GetObjectData(info, context);
        }
    }

    [Serializable]
    public class LibraryBook : Book
    {
        private readonly DateTime _CheckedOut;

        public LibraryBook(string title, DateTime checkedOut)
            : base(title)
        {
            _CheckedOut = checkedOut;
        }

        protected LibraryBook(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            _CheckedOut = info.GetDateTime("CheckedOut");
        }

        public DateTime CheckedOut
        {
            get { return _CheckedOut; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        protected override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("CheckedOut", _CheckedOut);
        }
    }
}

स्वीकृत उत्तर इतना आश्वस्त है कि मेरा मानना ​​है कि यह बग नहीं था। लेकिन अब कुछ प्रयोग करने के बाद मैं कह सकता हूं कि Level2 सुरक्षा पूरी तरह से गड़बड़ है; कम से कम, वास्तव में कुछ गड़बड़ है।

कुछ दिनों पहले मैं अपने पुस्तकालयों के साथ इसी मुद्दे पर टकराया था। मैंने जल्दी से एक इकाई परीक्षण बनाया; हालाँकि, मैं .NET फ़ेल्ड में अनुभव की गई समस्या को पुन: पेश नहीं कर सका, जबकि एक ही कोड "सफलतापूर्वक" ने एक कंसोल ऐप में अपवाद को फेंक दिया। अंत में मुझे इस मुद्दे पर काबू पाने के लिए दो अजीब तरीके मिले।

TL; DR : यह पता चला है कि यदि आप अपने उपभोक्ता प्रोजेक्ट में आंतरिक प्रकार के उपयोग किए गए पुस्तकालय का उपयोग करते हैं, तो आंशिक रूप से विश्वसनीय कोड अपेक्षित रूप से काम करता है: यह एक ISerializable कार्यान्वयन (और सुरक्षा महत्वपूर्ण कोड को सीधे कॉल नहीं किया जा सकता है) , लेकिन नीचे देखें)। या, जो और भी हास्यास्पद है, आप सैंडबॉक्स को फिर से बनाने की कोशिश कर सकते हैं यदि यह पहली बार काम नहीं करता ...

लेकिन कुछ कोड देखते हैं।

ClassLibrary.dll:

चलो दो मामलों को अलग करते हैं: एक नियमित सुरक्षा सामग्री के साथ एक नियमित वर्ग के लिए और एक ISerializable कार्यान्वयन:

public class CriticalClass
{
    public void SafeCode() { }

    [SecurityCritical]
    public void CriticalCode() { }

    [SecuritySafeCritical]
    public void SafeEntryForCriticalCode() => CriticalCode();
}

[Serializable]
public class SerializableCriticalClass : CriticalClass, ISerializable
{
    public SerializableCriticalClass() { }

    private SerializableCriticalClass(SerializationInfo info, StreamingContext context) { }

    [SecurityCritical]
    public void GetObjectData(SerializationInfo info, StreamingContext context) { }
}

समस्या को दूर करने का एक तरीका उपभोक्ता विधानसभा से आंतरिक प्रकार का उपयोग करना है। कोई भी प्रकार यह करेगा; अब मैं एक विशेषता को परिभाषित करता हूं:

[AttributeUsage(AttributeTargets.All)]
internal class InternalTypeReferenceAttribute : Attribute
{
    public InternalTypeReferenceAttribute() { }
}

और संबंधित विशेषताओं को विधानसभा में लागू किया जाता है:

[assembly: InternalsVisibleTo("UnitTest, PublicKey=<your public key>")]
[assembly: AllowPartiallyTrustedCallers]
[assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)]

असेंबली पर हस्ताक्षर करें, InternalsVisibleTo विशेषता के लिए कुंजी लागू करें और परीक्षण परियोजना के लिए तैयार करें:

UnitTest.dll (NUnit और ClassLibrary का उपयोग करता है):

आंतरिक चाल का उपयोग करने के लिए परीक्षण विधानसभा पर भी हस्ताक्षर किए जाने चाहिए। विधानसभा विशेषताएं:

// Just to make the tests security transparent by default. This helps to test the full trust behavior.
[assembly: AllowPartiallyTrustedCallers] 

// !!! Comment this line out and the partial trust test cases may fail for the fist time !!!
[assembly: InternalTypeReference]

नोट : विशेषता कहीं भी लागू की जा सकती है। मेरे मामले में यह एक यादृच्छिक परीक्षण कक्षा में एक विधि पर था मुझे खोजने में कुछ दिन लगे।

नोट 2 : यदि आप सभी परीक्षण विधियों को एक साथ चलाते हैं तो ऐसा हो सकता है कि परीक्षण पास हो जाएंगे।

परीक्षण वर्ग का कंकाल:

[TestFixture]
public class SecurityCriticalAccessTest
{
    private partial class Sandbox : MarshalByRefObject
    {
    }

    private static AppDomain CreateSandboxDomain(params IPermission[] permissions)
    {
        var evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
        var permissionSet = GetPermissionSet(permissions);
        var setup = new AppDomainSetup
        {
            ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
        };

        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        var strongNames = new List<StrongName>();
        foreach (Assembly asm in assemblies)
        {
            AssemblyName asmName = asm.GetName();
            strongNames.Add(new StrongName(new StrongNamePublicKeyBlob(asmName.GetPublicKey()), asmName.Name, asmName.Version));
        }

        return AppDomain.CreateDomain("SandboxDomain", evidence, setup, permissionSet, strongNames.ToArray());
    }

    private static PermissionSet GetPermissionSet(IPermission[] permissions)
    {
        var evidence = new Evidence();
        evidence.AddHostEvidence(new Zone(SecurityZone.Internet));
        var result = SecurityManager.GetStandardSandbox(evidence);
        foreach (var permission in permissions)
            result.AddPermission(permission);
        return result;
    }
}

और आइए एक-एक करके परीक्षण मामलों को देखें

केस 1: ISerializable कार्यान्वयन

प्रश्न में जैसा मुद्दा है। परीक्षा पास हो जाती है

  • InternalTypeReferenceAttribute लागू किया गया है
  • सैंडबॉक्स को कई बार बनाने की कोशिश की जाती है (कोड देखें)
  • या, यदि सभी परीक्षण मामलों को एक ही बार में निष्पादित किया जाता है और यह पहला नहीं है

अन्यथा, Inheritance security rules violated while overriding member... पूरी तरह से अनुचित Inheritance security rules violated while overriding member... अपवाद जब आप SerializableCriticalClass

[Test]
[SecuritySafeCritical] // for Activator.CreateInstance
public void SerializableCriticalClass_PartialTrustAccess()
{
    var domain = CreateSandboxDomain(
        new SecurityPermission(SecurityPermissionFlag.SerializationFormatter), // BinaryFormatter
        new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)); // Assert.IsFalse
    var handle = Activator.CreateInstance(domain, Assembly.GetExecutingAssembly().FullName, typeof(Sandbox).FullName);
    var sandbox = (Sandbox)handle.Unwrap();
    try
    {
        sandbox.TestSerializableCriticalClass();
        return;
    }
    catch (Exception e)
    {
        // without [InternalTypeReference] it may fail for the first time
        Console.WriteLine($"1st try failed: {e.Message}");
    }

    domain = CreateSandboxDomain(
        new SecurityPermission(SecurityPermissionFlag.SerializationFormatter), // BinaryFormatter
        new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)); // Assert.IsFalse
    handle = Activator.CreateInstance(domain, Assembly.GetExecutingAssembly().FullName, typeof(Sandbox).FullName);
    sandbox = (Sandbox)handle.Unwrap();
    sandbox.TestSerializableCriticalClass();

    Assert.Inconclusive("Meh... succeeded only for the 2nd try");
}

private partial class Sandbox
{
    public void TestSerializableCriticalClass()
    {
        Assert.IsFalse(AppDomain.CurrentDomain.IsFullyTrusted);

        // ISerializable implementer can be created.
        // !!! May fail for the first try if the test does not use any internal type of the library. !!!
        var critical = new SerializableCriticalClass();

        // Critical method can be called via a safe method
        critical.SafeEntryForCriticalCode();

        // Critical method cannot be called directly by a transparent method
        Assert.Throws<MethodAccessException>(() => critical.CriticalCode());
        Assert.Throws<MethodAccessException>(() => critical.GetObjectData(null, new StreamingContext()));

        // BinaryFormatter calls the critical method via a safe route (SerializationFormatter permission is required, though)
        new BinaryFormatter().Serialize(new MemoryStream(), critical);
    }

}

केस 2: सुरक्षा महत्वपूर्ण सदस्यों के साथ नियमित कक्षा

परीक्षण पहले वाले के समान शर्तों से गुजरता है। हालाँकि, समस्या पूरी तरह से यहाँ है: एक आंशिक रूप से विश्वसनीय कोड सीधे सुरक्षा महत्वपूर्ण सदस्य तक पहुँच सकता है

[Test]
[SecuritySafeCritical] // for Activator.CreateInstance
public void CriticalClass_PartialTrustAccess()
{
    var domain = CreateSandboxDomain(
        new ReflectionPermission(ReflectionPermissionFlag.MemberAccess), // Assert.IsFalse
        new EnvironmentPermission(PermissionState.Unrestricted)); // Assert.Throws (if fails)
    var handle = Activator.CreateInstance(domain, Assembly.GetExecutingAssembly().FullName, typeof(Sandbox).FullName);
    var sandbox = (Sandbox)handle.Unwrap();
    try
    {
        sandbox.TestCriticalClass();
        return;
    }
    catch (Exception e)
    {
        // without [InternalTypeReference] it may fail for the first time
        Console.WriteLine($"1st try failed: {e.Message}");
    }

    domain = CreateSandboxDomain(
        new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)); // Assert.IsFalse
    handle = Activator.CreateInstance(domain, Assembly.GetExecutingAssembly().FullName, typeof(Sandbox).FullName);
    sandbox = (Sandbox)handle.Unwrap();
    sandbox.TestCriticalClass();

    Assert.Inconclusive("Meh... succeeded only for the 2nd try");
}

private partial class Sandbox
{
    public void TestCriticalClass()
    {
        Assert.IsFalse(AppDomain.CurrentDomain.IsFullyTrusted);

        // A type containing critical methods can be created
        var critical = new CriticalClass();

        // Critical method can be called via a safe method
        critical.SafeEntryForCriticalCode();

        // Critical method cannot be called directly by a transparent method
        // !!! May fail for the first time if the test does not use any internal type of the library. !!!
        // !!! Meaning, a partially trusted code has more right than a fully trusted one and is       !!!
        // !!! able to call security critical method directly.                                        !!!
        Assert.Throws<MethodAccessException>(() => critical.CriticalCode());
    }
}

केस 3-4: केस के पूर्ण ट्रस्ट संस्करण 1-2

पूर्णता की खातिर यहां वही मामले हैं जो पूरी तरह से विश्वसनीय डोमेन में निष्पादित किए गए हैं। यदि आप [assembly: AllowPartiallyTrustedCallers] को [assembly: AllowPartiallyTrustedCallers] , तो परीक्षण विफल हो जाते हैं क्योंकि तब आप महत्वपूर्ण कोड को सीधे एक्सेस कर सकते हैं (क्योंकि विधियां डिफ़ॉल्ट रूप से पारदर्शी नहीं हैं)।

[Test]
public void CriticalClass_FullTrustAccess()
{
    Assert.IsTrue(AppDomain.CurrentDomain.IsFullyTrusted);

    // A type containing critical methods can be created
    var critical = new CriticalClass();

    // Critical method cannot be called directly by a transparent method
    Assert.Throws<MethodAccessException>(() => critical.CriticalCode());

    // Critical method can be called via a safe method
    critical.SafeEntryForCriticalCode();
}

[Test]
public void SerializableCriticalClass_FullTrustAccess()
{
    Assert.IsTrue(AppDomain.CurrentDomain.IsFullyTrusted);

    // ISerializable implementer can be created
    var critical = new SerializableCriticalClass();

    // Critical method cannot be called directly by a transparent method (see also AllowPartiallyTrustedCallersAttribute)
    Assert.Throws<MethodAccessException>(() => critical.CriticalCode());
    Assert.Throws<MethodAccessException>(() => critical.GetObjectData(null, default(StreamingContext)));

    // Critical method can be called via a safe method
    critical.SafeEntryForCriticalCode();

    // BinaryFormatter calls the critical method via a safe route
    new BinaryFormatter().Serialize(new MemoryStream(), critical);
}

उपसंहार:

बेशक, यह आपकी समस्या को .NET Fiddle के साथ हल नहीं करेगा। लेकिन अब मुझे बहुत आश्चर्य होगा अगर यह फ्रेम में बग नहीं था।

मेरे लिए अब सबसे बड़ा प्रश्न स्वीकृत उत्तर में उद्धृत भाग है। वे इस बकवास के साथ कैसे निकले? ISafeSerializationData स्पष्ट रूप से किसी भी चीज़ का समाधान नहीं है: इसका उपयोग विशेष रूप से बेस Exception क्लास द्वारा किया जाता है और यदि आप SerializeObjectState ईवेंट की सदस्यता लेते हैं (क्यों कि यह एक अतिव्याप्त विधि नहीं है?), तो राज्य भी Exception.GetObjectData द्वारा उपभोग किया जाएगा? अंततः।

AllowPartiallyTrustedCallers / SecurityCritical / SecuritySafeCritical विशेषताओं के बारे में ऊपर दिखाए गए उपयोग के लिए AllowPartiallyTrustedCallers रूप से डिज़ाइन किए गए थे। यह मेरे लिए कुल बकवास लगता है कि आंशिक रूप से विश्वसनीय कोड भी अपने सुरक्षा महत्वपूर्ण सदस्यों का उपयोग करने के प्रयास की परवाह किए बिना एक प्रकार का संकेत नहीं दे सकता है। लेकिन यह और भी बड़ा बकवास है ( सुरक्षा छेद वास्तव में) जो आंशिक रूप से भरोसेमंद कोड सीधे सुरक्षा महत्वपूर्ण विधि तक पहुंच सकता है ( केस 2 देखें) जबकि यह पूरी तरह से विश्वसनीय डोमेन से भी पारदर्शी तरीकों के लिए मना किया गया है।

इसलिए यदि आपकी उपभोक्ता परियोजना एक परीक्षण या अन्य प्रसिद्ध विधानसभा है, तो आंतरिक चाल का उपयोग पूरी तरह से किया जा सकता है। .NET फ़िडल और अन्य वास्तविक जीवन के सैंडबॉक्स वाले वातावरण के लिए एकमात्र समाधान SecurityRuleSet.Level1 वापस आ रहा है जब तक कि यह Microsoft द्वारा तय नहीं किया जाता है।

अद्यतन: इस मुद्दे के लिए एक डेवलपर समुदाय टिकट बनाया गया है।


second अनुसार, .NET 4.0 में मूल रूप से आपको आंशिक रूप से विश्वसनीय कोड के लिए ISerializable उपयोग नहीं करना चाहिए, और इसके बजाय आपको ISafeSerializationData उपयोग करना चाहिए

second से उद्धरण

जरूरी

.NET फ्रेमवर्क 4.0 के पिछले संस्करणों में, GetObjectData का उपयोग करके आंशिक रूप से विश्वसनीय विधानसभा में कस्टम उपयोगकर्ता डेटा के क्रमांकन को पूरा किया गया था। संस्करण 4.0 से शुरू होकर, उस विधि को SecurityCriticalAttribute विशेषता के साथ चिह्नित किया गया है जो आंशिक रूप से विश्वसनीय असेंबलियों में निष्पादन को रोकता है। इस स्थिति के आसपास काम करने के लिए, ISafeSerializationData इंटरफ़ेस लागू करें।

तो शायद नहीं जो आप सुनना चाहते थे यदि आपको इसकी आवश्यकता है, लेकिन मुझे नहीं लगता कि ISerializable का उपयोग करते समय इसके आसपास कोई रास्ता नहीं है ( Level1 सुरक्षा पर वापस जाने के अलावा, जो आपने कहा था कि आप नहीं चाहते हैं)।

पुनश्च: ISafeSerializationData डॉक्स का कहना है कि यह सिर्फ अपवादों के लिए है, लेकिन यह सब विशिष्ट नहीं लगता है, आप इसे शॉट देना चाह सकते हैं ... मैं मूल रूप से इसे आपके नमूना कोड ( ISerializable को हटाने के अलावा) के साथ परीक्षण नहीं कर सकता काम करता है, लेकिन आप पहले से ही जानते थे कि ... आपको यह देखना होगा कि क्या ISafeSerializationData आपको पर्याप्त सूट करता है।

PS2: SecurityCritical विशेषता काम नहीं करती है क्योंकि जब विधानसभा को आंशिक विश्वास मोड ( Level2 सुरक्षा पर ) में लोड किया जाता है तो इसे अनदेखा कर दिया जाता है। आप इसे अपने नमूना कोड पर देख सकते हैं, यदि आप इसे लागू करने से ठीक पहले ExecuteUntrustedCode में target चर को डीबग करते हैं, तो इसके पास IsSecurityTransparent true और IsSecurityCritical को false करने के लिए होगा, भले ही आप SecurityCritical विधि के साथ विधि को चिह्नित करें)







code-access-security