C#学习教程:从未经授权的调用者处保护C#程序集不是我们公司签的?我想在不需要任何强命名(如使用StrongNameIdentityPermission)的情况下执行此操作,并坚持程序集的签名方式。我真的不想使用InternalsVisibleTo属性,因为它在不断变化的软件生态系统中不可维护。例如:场景一Foo.dll由我公司签名,Bar.dll根本没有签名。Foo的A类栏有B类A类有公共方法GetSomething()和B类试图调用Foo.A.GetSomething()并被拒绝被拒绝可能是一个例外,或者以某种方式被忽略场景二Foo.dll由我签名公司,Moo.dll也是我公司签名的。Foo有A类Moo有C类A有公共方法GetSomething()C类试图调用Foo.A.GetSomething()并且没有被拒绝如果你想限制调用者只能使用特定证书签名的代码,你仍然可以使用CAS(而不是StrongNameIdentityPermission)。使用PublisherIdentityPermission就像使用任何CAS权限一样。或者,如果您想以声明方式执行此操作,请使用属性.显然,您必须对被调用方法中的每个调用执行检查——任何试图强制执行限制的外部系统都可以使用反射轻松绕过。从方法newStackTrace().GetFrame(1).GetMethod().Module.Assembly中,您可以使用它来获取调用程序集。现在您可以使用callingAssembly.GetName().GetPublicKey()获取调用程序集的公钥并将其与被调用程序集的公钥进行比较。如果它们匹配-假设所有程序集都使用相同的密钥对签名-调用者被认为是合法的。但存在一个漏洞——第3方程序集可能会延迟使用贵公司的公钥进行签名,并被排除在数字签名验证之外。因此,加载程序将加载具有强名称和公司公钥的第三方程序集,即使它尚未签名。要关闭此漏洞,您必须检查签名。没有托管API,您必须P/InvokeBooleanStrongNameSignatureVerificationEx(StringwszFilePath,BooleanfForceVerification,refBooleanpfWasVerified)将fForceVerification设置为true并检查结果是否为真。总而言之,每次调用都会有很大的开销。诱惑可能是缓存结果,但假设调用者具有反射权限,操作这样的缓存可能不是很困难。另一方面,您永远无法100%确定。控制系统的人(几乎)可以自由地做任何事情——附加调试器、修改内存内容、操纵库或整个运行时。最后,您还必须有效地保护您的程序集不被反编译和修改。首先,如您所知,仅使用InternalsVisibleTo是不够的——您还需要对每个程序集进行签名和强命名,以确保有人不能只是冒用该名称。既然这已经解决了,您将不得不自己开发一个挑战-响应实现——这不是您可以做的事情,除非您愿意使用您已明确描述的您不想要的InternalsVisibleTo方法。使用。在CR模型中,您需要在每次方法调用时传递某种令牌(或者只是为了实例化一个对象)。令牌将是一个只有您的代码才能创建其实例的类-我将其设为您要使用的程序集的内部类,并使其可通过InternalsVisibleTo访问-这样就只有一个类需要管理://SharedAssembly。dll//将ConsumingAssembly.dll标记为可以访问内部...//你可能想要一个自定义异常。//执行你的业务逻辑...returntrue;}}//ConsumingAssembly.dll(可以通过InternalsVisibleTo访问)publicclassMainClass{publicstaticvoidMain(){vartoken=newAccessToken();//可以创建这个因为IVT访问SecuredClass.WorkMethod(token,"");//tada...}}您可能希望将AccessToken类放在服务提供者和消费者都知道程序集的第三方中,这样您就不必为不同的程序集维护不同的访问令牌类集。为每个方法建立一个CR机制是繁琐和繁琐的。它也不是100%万无一失的——有足够时间和耐心的人可能会找到解决方法。最好的选择(在您的情况下可能可行也可能不可行)是将您的私有代码保存在您自己的服务器上,并且只将其作为Web服务(或类似的东西)公开。这使您能够主动管理IP可访问性,并允许您以集中(而非分布式)方式更新访问者。已经存在使用证书、消息签名和加密来限制对Web服务的访问的技术。这将是控制对您的IP的访问的最可靠(和经过验证)的方式。我见过使用挑战/响应系统解锁组件的公司(最著名的是PegasusImaging)编写的DLL。DLL的购买者提供带有“购买者名称”的“许可证代码”,DLL的消费者随后使用该代码来解锁DLL功能的特定子集。因此,当应用程序第一次使用程序集时,会调用程序集中的Unlock()方法。用户名和解锁代码被传入并运行验证身份的算法,可能使用某种公钥加密算法。解锁代码中有指定功能的位;这些位然后在汇编中设置一些功能标志。所有调用函数都必须检查这些标志以确定是否启用了相应的功能。Unlock()方法仅在加载的程序集的生命周期内被调用一次。当然,由于您必须在程序集中提供“私钥”,因此该程序不是防黑客的(什么是?),但它相当安全并且可以让诚实的人保持诚实。我觉得没什么大不了的!如果您真的需要安全性,请将您的代码放在服务器后面并使用客户端-服务器架构。或者网络服务。或者像WCF或远程处理之类的东西。然后使用身份验证对客户端进行身份验证。哎呀,您可以将所有内容保密,公开一个公共API并在本地将其称为root。在纯桌面环境中保护DLL免受未经授权的调用者的攻击只会使事情变得更加复杂和难以使用。更不用说内部看起来很丑了。我看到一些约定出现了。这可能对你有用。但它并没有给你你想要的“完全安全”。如果您有一个应该对客户隐藏的程序集,请不要将它放在GAC中。使用带有后缀“INTERNAL”的名称空间。如果您不控制代码运行的执行环境,我认为没有办法实现这一目标。在用户计算机上以完全信任的方式运行的代码将能够绕过您添加的任何限制。例如,完全信任代码可以使用reflectionAPI来调用私有或内部方法,因此即使使用InternalsVisibleToAttribute也不行。如果您控制执行环境,则可以创建一个AppDomain,其中您的代码是完全受信任的,第3方代码是部分受信任的,除非您将AllowPartiallyTrustedCallersAttribute(APTCA)放在程序集上,否则无法调用您的代码。您可以使用SecurityCritical和SecuritySafeCritical属性限制可以在APTCA程序集中调用的方法。HowTo:RunPartiallyTrustedCodeinaSandboxThat'sallforC#LearnTutorial:SecureC#AssembliesfromUnauthorizedCallers如果对大家有用,需要了解更多C#LearnTutorial,希望大家多多关注——这篇文章收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
