如何检测我的代码是不是应该模拟?

Posted

技术标签:

【中文标题】如何检测我的代码是不是应该模拟?【英文标题】:How can I detect if my code should Impersonate or not?如何检测我的代码是否应该模拟? 【发布时间】:2012-05-11 04:10:52 【问题描述】:

我的代码作为事件处理程序的一部分运行,需要创建一个新的 TOM.NET 会话(我不能重用 subject.Session)。此事件处理程序被加载到许多 Tridion 进程(TcmServiceHost、COM+、Publisher、TcmTemplateDebugHost、IIS 应用程序池)中,这些进程可能:

在可以访问 Tridion 的身份下运行(例如,COM+ 应用程序在 MTSUser 下运行,它是 Tridion 管理员) 以无权访问 Tridion 但允许模拟 Tridion 用户的身份运行(例如,TcmServiceHost 作为 NetworkService 运行,配置为 Tridion 模拟用户)。

我尝试用这个 TOM.NET 代码来满足这两种情况:

Session session = null;
try

    session = new Session();

catch (AccessDeniedException ex)

    // this process doesn't have TCM access, so impersonate a user that does
    session = new Session("Administator");

if (session != null)

    var item = session.GetObject(id);
    ...

这是检查我的代码是否在有权访问 Tridion 的进程下运行的正确方法(忽略我硬编码“管理员”的事实)?该代码有效,但我只是想知道是否有更有效的方法来执行“有权访问 Tridion”检查?

注意:当我使用 Core Service 访问 Tridion 时,也会出现同样的问题,所以问题不在于 TOM.NET 是否是此处使用的正确 API。

【问题讨论】:

【参考方案1】:

我不会使用此代码。异常捕获速度很慢,您目前正在向无法访问系统的任何人授予(管理员)访问权限 - 这是一个很大的安全漏洞。

相反,我会查看当前用户是谁,并确定他是否是模拟用户。如果没有 API(我没有检查),您可以直接从 Tridion.ContentManager.config 文件中读取模拟用户。

var isImpersonationUser = IsImpersonationUser(WindowsIdentity.GetCurrent());
var session = isImpersonationUser ? new Session("Administrator") : new Session();
var item = session.GetObject(id);

或者您可以为您的事件代码单独配置它。甚至硬编码,如果你不关心代码是通用的。

【讨论】:

谢谢彼得。从 TCM 配置中读取模拟用户是一个好主意。我今天试了一下,似乎奏效了。 不,Peter,他没有将管理员访问权限授予“任何无法访问系统的人”,而是授予不是 Tridion 受托人,而是 /are/ 模拟用户的身份。这种区别至关重要:模拟用户应该能够模拟任何受托人,包括管理员。 如果您确实想从配置中读取模拟用户,我认为从内存缓存中获取这些数据比直接访问文件更好,因此至少使用配置 API 会更好对于像 Puf 这样对支持毫无疑问的“内部人员”。 @DominicCronin true,如果您不是模拟用户,系统将不允许您模拟。所以安全影响比我最初想象的要小。但在我看来,代码仍然是不可取的。例如,如果用户可以访问系统但不能访问任何出版物怎么办。从本质上讲,代码与他的意图不符,其他人很难阅读代码并准确理解它试图做什么。 @PeterKjaer 是的 - 我同意你的看法。我已经写了一个更全面地描述我的观点的答案【参考方案2】:

这段代码对我来说似乎非常有效 - 但通过检查您是否可以创建会话对象并不能保证代码将能够执行您希望在 CMS 中实际执行的操作。

这样的代码似乎也造成了一个巨大的安全漏洞,允许进程在没有权限时回退到更高级别的安全性。另请记住,如果您正在修改 CMS 中的任何项目,则该冒充将导致不显示可能触发更改的个人的真实姓名。它将作为您模拟的用户存储。

【讨论】:

感谢您的反馈。我已经担心不会有更好的机制了。 :-/ 事件处理程序不对内容管理器中的任何数据进行任何修改,但确实需要对可能很大的一组系统内容进行只读访问。在这种情况下,需要一个可配置的“管理员”用户是很常见的。它确实需要我的代码注意它不会让任何用户通常无法访问的信息逃逸。别担心,它没有。 :-)【参考方案3】:

首先,这是一个很好的问题/主题。

我认为您正在尝试“构建”可以在每个 Tridion 流程上运行的通用程序。在我看来,您应该知道您何时处于一个或另一个流程中,因为根据最佳实践(R&D/you),我们不应该创建 Session 对象,而是在那些没有的流程中使用核心服务访问 Session 对象并尽可能重用可用的会话。

正如你在模板和事件系统中所知道的,例如,我们可以访问 Session,所以我们应该重用它(除非我们想做用户不允许做的事情,在这种情况下我们应该模拟) .

如果在另一个进程中会话不可用,您应该使用核心服务。

所以我对你的问题的回答是不要使用 TOM.NET。我会改变我的方法并使用核心服务构建它,我可以在其中模拟我之前已经配置的特定用户。而且您的代码会更通用,并且可以“随处”运行(但不是在烤面包机中)。

我了解您在此处试图确定的内容,“到底是谁在运行我当前的进程”?所以你可以相应地模仿,

不幸的是(AFAIK),您必须编写一些代码来查看谁是运行该进程的身份,然后进行相应的模拟。这很棘手,这也是我再次建议使用核心服务而不是 TOM.NET API 的原因。

希望这是有道理的。

【讨论】:

我使用 TOM.NET 和核心服务的实现完全相同。但是核心服务变体也有同样的问题(if-fail-then-imersonate)并且更加冗长。这就是我选择发布代码的 TOM.NET 版本的原因。【参考方案4】:

在最初实现 TDSE.Impersonate() 方法时,它被有意设计为在调用线程标识不是模拟用户时静默失败。例如,这允许当时 GUI 中的 ASP 代码盲目地尝试模拟(基于 REMOTE_USER 标头 IIRC)。关键是,如果您不是冒充用户,好吧,好吧,您可以做您自己,但如果您是,您可以/将会冒充。

我刚刚使用 COM API 对此进行了测试(我将由您来验证 .NET API 是否一致)。我的结果(在 Tridion 2011 SP1 上)如下:

1)。作为受托人并且不冒充的冒充用户成为他自己。 2)。作为受托人和模拟的模拟用户将成为他们模拟的任何人(注意,您通常不希望创建这样的用户)。 3)。调用 impersonate 的非模拟用户仍然是他自己。

显然,很大程度上取决于进程身份是否是模拟用户。在某些情况下,您可能更愿意避免使用 NETWORK SERVICE 并为 TcmServiceHost 显式创建一个身份,只是为了允许对此类用户是否可以模拟进行细粒度控制。

那么...您是否需要明确测试您的进程是否作为模拟程序运行?简单地尝试模仿并接受结果可能会更好。最初的想法当然包括这个意图,但我怀疑事情已经变得更加复杂。

+1 对于这个问题,因为毫无疑问,这一领域的预期行为是绝对必要的。

【讨论】:

模拟不再默默失败。 那么很大程度上取决于异常的针对性。 我已经搞砸了,看起来你几乎所有的事情都得到了 AccessDeniedException

以上是关于如何检测我的代码是不是应该模拟?的主要内容,如果未能解决你的问题,请参考以下文章

检测和求和年、月和日

Android - 如何检测应用程序是否在Nox模拟器上运行?

如何判断是不是被检测到使用模拟器了

如何检测应用程序正在模拟器或设备上运行[重复]

在代码中检测iOS模拟器中慢速动画是不是打开/关闭

在 android 模拟器中模拟 GPS 路线