异步 WCF 最终方法中的 Thread.CurrentPrincipal 错误

2024-06-23

我有一个 WCF 服务,它有Thread.CurrentPrincipal设置在ServiceConfiguration.ClaimsAuthorizationManager.

当我像这样异步实现服务时:

    public IAsyncResult BeginMethod1(AsyncCallback callback, object state)
    {
        // Audit log call (uses Thread.CurrentPrincipal)

        var task = Task<int>.Factory.StartNew(this.WorkerFunction, state);

        return task.ContinueWith(res => callback(task));
    }

    public string EndMethod1(IAsyncResult ar)
    {
        // Audit log result (uses Thread.CurrentPrincipal)

        return ar.AsyncState as string;
    }

    private int WorkerFunction(object state)
    {
        // perform work
    }

我发现 Thread.CurrentPrincipal 在 Begin 方法和 WorkerFunction 中设置为正确的 ClaimsPrincipal,但在 End 方法中它设置为 GenericPrincipal。

我知道我可以为服务启用 ASP.NET 兼容性并使用HttpContext.Current.User它在所有方法中都有正确的原理,但我宁愿不这样做。

有没有办法在不打开 ASP.NET 兼容性的情况下强制 Thread.CurrentPrincipal 为正确的 ClaimsPrincipal?


从一个开始WCF扩展点总结 http://sankarsan.wordpress.com/2008/12/28/wcf-extension-points-dispatcher/,您会看到专门为解决您的问题而设计的。它被称为调用上下文初始化器 http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.icallcontextinitializer%28v=vs.110%29.aspx。看看这个文章给出了 CallContextInitializer 示例代码 http://blogs.msdn.com/b/carlosfigueira/archive/2012/02/14/wcf-extensibility-initializers-instance-context-channel-call-context.aspx.

如果您进行 ICallContextInitializer 扩展,您将获得对 BeginXXX 线程上下文的控制ANDEndXXX 线程上下文。您是说 ClaimsAuthorizationManager 已在 BeginXXX(...) 方法中正确建立了用户主体。在这种情况下,您可以为自己创建一个自定义 ICallContextInitializer,它可以分配或记录 CurrentPrincipal,具体取决于它是处理 BeginXXX() 还是 EndXXX()。就像是:

public object BeforeInvoke(System.ServiceModel.InstanceContext instanceContext, System.ServiceModel.IClientChannel channel, System.ServiceModel.Channels.Message request){
    object principal = null;
    if (request.Properties.TryGetValue("userPrincipal", out principal))
    {
        //If we got here, it means we're about to call the EndXXX(...) method.
        Thread.CurrentPrincipal = (IPrincipal)principal;
    }
    else
    {
        //If we got here, it means we're about to call the BeginXXX(...) method.
        request.Properties["userPrincipal"] = Thread.CurrentPrincipal;            
    }
    ...
 }

为了进一步澄清,考虑两种情况。假设您实现了 ICallContextInitializer 和 IParameterInspector。假设这些挂钩预计使用同步 WCF 服务和异步 WCF 服务(这是您的特殊情况)执行。

以下是事件的顺序以及所发生事件的解释:

同步案例

ICallContextInitializer.BeforeInvoke();
IParemeterInspector.BeforeCall();
//...service executes...
IParameterInspector.AfterCall();
ICallContextInitializer.AfterInvoke();

上面的代码没有什么奇怪的。但现在看看下面异步服务操作会发生什么......

异步案例

ICallContextInitializer.BeforeInvoke();  //TryGetValue() fails, so this records the UserPrincipal.
IParameterInspector.BeforeCall();
//...Your BeginXXX() routine now executes...
ICallContextInitializer.AfterInvoke();

//...Now your Task async code executes (or finishes executing)...

ICallContextInitializercut.BeforeInvoke();  //TryGetValue succeeds, so this assigns the UserPrincipal.
//...Your EndXXX() routine now executes...
IParameterInspector.AfterCall();
ICallContextInitializer.AfterInvoke();

正如您所看到的,CallContextInitializer 确保您有机会在 EndXXX() 例程运行之前初始化值,例如 CurrentPrincipal。因此,EndXXX() 例程确实在与 BeginXXX() 例程不同的线程上执行并不重要。是的,System.ServiceModel.Channels.Message即使线程发生更改,WCF 也会保留并正确传输在 Begin/End 方法之间存储用户主体的对象。

总的来说,这种方法允许您的 EndXXX(IAsyncresult) 使用正确的 IPrincipal 执行,而无需在 EndXXX() 例程中显式地重新建立 CurrentPrincipal。与任何 WCF 行为一样,您可以决定这是否适用于单个操作、合约上的所有操作或端点上的所有操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

异步 WCF 最终方法中的 Thread.CurrentPrincipal 错误 的相关文章

随机推荐

  • BulkRequestBuilder 的 Elasticsearch 索引速度变慢

    大家好 elasticsearch 大师们 我有数百万数据需要由elasticsearch Java API 索引 Elasticsearch 的集群节点数量为 3 个 1 个主节点 2 个节点 我的代码片段如下 Settings sett
  • 使用 SVG 多边形元素

    我正在尝试使用 SVG 多边形和 javascript 我创建一个多边形并设置其初始点列表 如下所示 var polygon document createElementNS http www w3 org 2000 svg polygon
  • 带箭头的样式项目符号列表

    我创建了一个箭头 我想将其附加到列表而不是圆形项目符号点 我尝试过使用 after 但还没有成功 不得不承认我对伪元素非常陌生 这是我到目前为止得到的 arrow border right 2px solid black border bo
  • 通过 HTTPS/SSL 的 Java 客户端证书

    我正在使用 Java 6 并尝试创建一个HttpsURLConnection使用客户端证书针对远程服务器 服务器使用自签名根证书 并要求提供受密码保护的客户端证书 我已将服务器根证书和客户端证书添加到我在其中找到的默认 java 密钥库中
  • 父视图控制器如何通知其子视图控制器已删除自身?

    子视图控制器的实现中通过以下代码删除子视图控制器 void commandFinishVC self view removeFromSuperview self removeFromParentViewController 子视图控制器及其
  • SQLite 用于大数据集?

    我有一个相当大的数据集 并且希望将其存储在文件中而不是 RDBMS 中 数据集中的主表的 CSV 大小刚刚超过 100 万行 30 列 大小约为 600Mb 我正在考虑 SQLite 对于这种大小的数据集 SQLite 值得研究吗 SQLi
  • Android:为什么系统重启后警报通知停止

    我正在开发一个 Android 应用程序 每天应该触发五次警报 每天的时间不是固定的 警报响起后 我将安排下一个警报 我的问题是 警报通知有效 1 天 然后停止 并且当设备重新启动两次时 通知不起作用 我现在不知道是否有其他方法可以做到这一
  • Swift:延迟封装映射、过滤器、FlatMap 链

    我有一份动物清单 let animals bear dog cat 以及一些改变该列表的方法 typealias Transform String gt String let containsA Transform 0 contains a
  • 如何添加 glassfish 工具到 eclipseoxy 3a

    我下载了 Eclipse Oxygen 但我没有在此 IDE 中安装 glassfish 工具 它是在 JDK 8 Update 172 上运行的 Oxygen 3A 64 位 当我尝试通过 Marketplace 安装这些工具时 它指出这
  • SQL在单个命令中在表中添加列和注释

    我的 Web 应用程序使用 Oracle 11g 我想向现有表添加列和注释 我可以使用以下命令轻松做到这一点 ALTER TABLE product ADD product description VARCHAR2 20 and COMME
  • AngularJS - 您可以在不修改其核心源代码的情况下重命名服务吗?

    我遇到过这样的情况 我下载了书面服务angular js 并且它工作得很好 但我更愿意在我的代码中将其称为不同的名称 只是为了方便和可读性 这并不是真正的要求 只是一种愿望 我可以在服务的实际源代码中仔细检查并更改它 但这显然会导致各种问题
  • 分区交换列类型或大小不匹配 (ORA-14097)

    我正在尝试对数据库进行交换分区 但出现以下错误 ORA 14097 ALTER TABLE EXCHANGE PARTITION 中的列类型或大小不匹配 剧本这样做已经创建了并且它在 Oracle 11g 数据库上按预期运行 当我更新到 1
  • 插入到子查询中具有多个值的表中

    INSERT INTO Reference TB RequestID WaveID VALUES 2222 select tWaveID from Table2 我正在使用上面的查询插入表中 我知道 Table2有多个tWaveID这就是为
  • Swift 中的精确字符串格式说明符

    下面是我之前如何将浮点数截断到小数点后两位 NSLog 02f 02f 02f r g b 我检查了文档和电子书 但无法弄清楚 谢谢 下面的代码 import Foundation required for String format pr
  • AWS RDS:从S3存储桶中的sql文件导入数据

    我有一个数据库备份作为 sql 文件存储在 s3 存储桶中 如何将该文件直接导入到 Aurora RDS 中 而不需要将其下载到我的 PC 上并手动导入 如果您的数据是有效的 SQL 转储 您可以在创建新的 Aurora 实例时指定其 S3
  • Google Groups API - getUsers() 您无权查看该群组的成员列表:

    大家干杯 我有一个 Google 脚本 它通过使用 getUsers 函数检查电子邮件地址是否是某个组的成员 So far 我已激活 Admin SDK目录服务 我有管理员权限 对于大多数组来说 它确实很神奇 但是在某些组的情况下我会收到授
  • CSS/Javascript:如何制作具有多种状态的旋转圆形菜单?

    通常我不会自己发布内容 我通常会通过其他人的线程找到我需要的内容 因此如果其中任何内容位于错误的位置或格式不正确 我很抱歉 我以前从来没有这样做过 所以情况是这样的 我正在尝试重建我的网站 并选择使用 WordPress 的 X 主题 大多
  • 使用ticker定期从经常变化的路径加载内存中的所有文件?

    我有一个应用程序需要从两个不同的路径读取文件 读取所有这些文件后 我需要将它们加载到内存中products map Path Full 这是内存中服务器启动期间需要加载的所有文件的路径 该路径将包含大约 50 个文件 每个文件大小约为 60
  • “正常”UIButton 导致 obj_stack_overflow 或 EXC_BAD_ACCESS 异常

    它看起来确实足够无害 在我的应用程序委托中 我检查NS用户默认值用于在启动时显示提示的标志 如果已设置 则在结束时applicationDidFinishLaunching 我这样做 TipsViewController vc TipsVi
  • 异步 WCF 最终方法中的 Thread.CurrentPrincipal 错误

    我有一个 WCF 服务 它有Thread CurrentPrincipal设置在ServiceConfiguration ClaimsAuthorizationManager 当我像这样异步实现服务时 public IAsyncResult