如何保护我的私有函数不受reflection执行的影响?

看到这个之后: 访问修饰符也会影响reflection吗?

我尝试使用它,但它不起作用: 在此处输入图像描述

如何防止reflection执行我的私有方法?

如果某人当前可以对您的私人方法使用reflection,那么他们已经有足够的权限来回避您放置的任何其他方式。 以较少的信任运行可能是一种选择,但这只是为了防止插件等访问过多 – 它不会阻止具有(例如)管理员访问权限的用户,该用户可以简单地提升访问权限。

如果您不希望代码运行,请不要将其置于恶意用户的物理范围内; 将它保存在网络服务或类似网站上。 用户可用的任何代码都可以直接使用,也可以通过反编译间接使用(如果需要,可以对其进行反混淆处理)。 你可以使用一些技巧来阻止他们(通过堆栈跟踪检查调用者等),但这不会阻止某人确定。

如何保护我的私有函数不受reflection执行的影响?

您可以更改安全策略,以便代码在运行时无权执行“私有reflection”。

当然,这只会影响您的机器。 如果您想影响其他人的计算机, 请向其计算机管理员发送电子邮件,并要求管理员更改用户的安全策略,以使其无权进行“私人反映”。 那是拥有机器及其运行的网络的人; 显然,您无法更改您不拥有的网络上的安全设置。

当然要注意,还必须限制比私人reflection更强大的权利。 设置一个政策说没有好处,例如“私人反映权被拒绝,但授予改变安全政策的权利”。 然后,用户可以只更改安全策略以重新授予对自己的私有reflection。

您还必须限制访问磁盘的能力。 可以访问磁盘的人可以简单地从程序集中读取代码,将私有元数据更改为public,并正常加载程序集。

因此,您的任务是说服全世界的所有机器管理员不允许其用户访问自己的磁盘。 我怀疑你会不会成功; 我建议您找到一种不同的方法来保护您的function免受滥用。

这是一个迟到的答案,但我认为这是一个更新,因为所有答案都是在2015年中期发布.NET 4.6之前编写的,它引入了一个名为DisablePrivateReflection的新程序集属性。

使用AssemblyInfo.cs标记的属性,可以禁用对该程序集的私有成员的reflection。

例:

 namespace DisablingPrivateReflection { public class Singleton { private Singleton() { } } } 

AssemblyInfo.cs添加以下行:

 [assembly: DisablePrivateReflection] 

然后在引用上述程序集的客户端程序集中,此代码将在运行时失败:

 var singleton = Activator.CreateInstance(typeof(Singleton), true); 

抛出的exception是MethodAccessException类型,带有消息:

尝试通过方法’Program.Main(System.String [])’访问方法’DisablingPrivateReflection.Singleton..ctor()’失败。

访问修饰符不是安全机制。

如果您可以阻止通过reflection调用函数,则用户可以只反编译程序,提取该函数,将其放入新程序集并执行它。

没有办法做到这一点。 为什么要阻止执行私有函数? 通常,如果有人使用reflection,他就知道自己在做什么。

你不能,修饰符只适合开发人员进行适当的封装。 在运行时,一切都处于同一水平可能会让人感到难过。

reflection机制通常由需要调用一些预配置方法(较旧的ORM)或显示它们(IDE)的应用程序使用。 如果这种机制无法做到这一点,那将非常困难。

虽然我完全同意访问修饰符不是安全function的想法,但仅仅是为了编程我一直在考虑这个问题,而且我有一个简单的,没有多少用处的机制,反思反思: – )

请注意,这只是一个愚蠢的概念certificate,我没有考虑通用方法,它需要改变…

这个想法是,在你想要“非法”调用的每个私有方法的开头,你只需通过Reflection检查你是从那个类中的另一个方法调用的,而不是从外部调用的。 所以你会使用:new StackTrace()。GetFrame(1).GetMethod(); 获取调用者的MethodBase,并将其与您的类的MethodInfos列表进行比较。

你可以把它添加到一个帮助类(无论如何你需要一个IEqualityComparer来比较MethodBases …

一个问题是你也会阻止一些正确的调用,比如通过委托调用它或者通过另一个方法调用reflection……所以你在使用它时应该小心。

你可以在这里实施

 using System; using System.Reflection; using System.Diagnostics; using System.Collections.Generic; using System.Linq; class Person { private string SayInternalSecure() { if (!PrivacyHelper.IsInvocationAllowed()) throw new Exception("you can't invoke this private method"); return "Internal Secure"; } private string SayInternal() { return "Internal"; } public string SaySomething() { return "Hi " + this.SayInternal(); } public string SaySomethingSecure() { return "Hi " + this.SayInternalSecure(); } public void BeingCalledBy() { Console.WriteLine("I'm being called by: " + new StackTrace().GetFrame(1).GetMethod().Name); } } public class MethodBaseComparer : IEqualityComparer { private string GetMethodIdentifier(MethodBase mb) { return mb.Name + ":" + String.Join(";", mb.GetParameters().Select(paramInfo=>paramInfo.Name).ToArray()); } public bool Equals(MethodBase m1, MethodBase m2) { //we need something more here, comparing just by name is not enough, need to take parameters into account return this.GetMethodIdentifier(m1) == this.GetMethodIdentifier(m2); } public int GetHashCode(MethodBase mb) { return this.GetMethodIdentifier(mb).GetHashCode(); } } class PrivacyHelper { static Dictionary cache = new Dictionary(); public static bool IsInvocationAllowed() { Type curType = typeof(T); if (!cache.ContainsKey(curType)) { cache[curType] = curType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToArray(); } //StackTrace.GetFrame returns a MethodBase, not a MethodInfo, that's why we're falling back to MethodBody MethodBase invoker = new StackTrace().GetFrame(2).GetMethod(); return cache[curType].Contains(invoker, new MethodBaseComparer()); } } public class App { public static void CheckCaller() { Person p = new Person(); Console.WriteLine("- calling via delegate"); Action action = p.BeingCalledBy; action(); Console.WriteLine("- calling via reflection"); MethodInfo method = typeof(Person).GetMethod("BeingCalledBy", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Console.WriteLine(method.Invoke(p, null)); Console.WriteLine("- calling via delegate again"); action = (Action)(Delegate.CreateDelegate(typeof(Action), p, method)); action(); } public static void Main() { Console.WriteLine("Press key to run"); Console.ReadLine(); CheckCaller(); Person p = new Person(); Console.WriteLine(p.SaySomething()); Console.WriteLine(p.SaySomethingSecure()); MethodInfo privateMethod = typeof(Person).GetMethod("SayInternal", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Console.WriteLine("invoking private method via Reflection:"); Console.WriteLine(privateMethod.Invoke(p, null)); Console.WriteLine("----------------------"); privateMethod = typeof(Person).GetMethod("SayInternalSecure", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Console.WriteLine("invoking secured private method via Reflection:"); try { Console.WriteLine(privateMethod.Invoke(p, null)); } catch(Exception ex) { Console.WriteLine(ex.Message); } } }