【问题标题】:OWIN losing Identity on OData $batch requestsOWIN 在 OData $batch 请求中失去身份
【发布时间】:2016-06-30 20:40:18
【问题描述】:

我正在尝试将我的标准 WebApi 应用程序移至 OWIN,但在身份和 $batch 请求方面存在问题。

我目前有一个DelegatingHandler 可以检测并分配SendAsync 中的身份:

// Detect bearer token and build the identity above.
IOwinContext owinContext = request.GetOwinContext();
owinContext.Authentication.User = new ClaimsPrincipal(identity);

对于正常请求,这将继续到ODataController.User。但是在 $batch 请求时,该属性将返回到未经身份验证的 ClaimsIdentity

即使GetOwinContext 返回一个IOwinContext 没有任何用户。我假设它为每个批次部分创建了一个新上下文,但我看不到任何找到原始上下文的方法。

任何帮助都会很棒!

【问题讨论】:

  • 您是否在任何地方使用.ConfigureAwait(false) 并从调用者发出await'? This would cause the http context not to be reused when execution resumes. Also it would be interesting to see what is actually sent to the server (like http headers) when a batch` 请求,可能故障在于客户端实现(如果未发送不记名令牌)而不是在服务器。您是否可以就此代码或相关代码提供任何其他见解?
  • 不,我没有在任何地方使用.ConfigureAwait(false)

标签: asp.net-web-api odata owin owin-middleware


【解决方案1】:

在您的 SendAsync 方法中尝试:

request.GetRequestContext().Principal = new ClaimsPrincipal(identity);

这将分配Thread.CurrentPrincipal 和当前的OWIN 上下文,(检查此link)。 我不是 100% 确定,但我的猜测是当前线程中没有设置 Principal,因为 OData 在不同线程中执行 $batch 子请求,并且 OWIN 上下文丢失了。

另一种选择是在 Configuration 方法中从 OWIN 中间件分配标识,而不是在 DelegatingHandler 中进行。这在此答案中进行了解释:https://stackoverflow.com/a/21420794/4067893,这也与您的问题有关。

希望对您有所帮助。

【讨论】:

  • 害怕也没用。 :(我之前试过第一种方法。app.Use((context, func)只对批处理请求调用,对子请求没有调用,所以身份仍然丢失。
  • 但是你说你的DelegatingHandler 中有identity,对吧?所以,好吧,忘记 OWIN 中间人,因为它只在批处理请求上而不是在子请求上被调用,并且在DelegatingHandler 中,设置request.GetRequestContext().Principal = new ClaimsPrincipal(identity);,就像我在回答中首先说的那样。很奇怪,这不起作用。 :( 我将在几个小时后再次尝试编辑我的答案。
  • 为 $batch 请求调用委托处理程序,并为 WebApi 的每个子请求再次调用。然而,OWIN 似乎为每个子请求创建了一个新线程,这不是标准 WebApi 所做的。以前他们的用户会落入孩子们的手中,但我不得不将身份加载到 OWIN 环境中,然后作为解决方法将其拉回。
【解决方案2】:

目前我找到了解决方法。如果有人找到更好的东西,我很乐意听到。

在我的DelegatingHandler 中,我已将身份存储在 OwinContext 环境中:

owinContext.Set<ClaimsIdentity>("customdata:identity", principal);

然后我创建了一个自定义的AuthorizeAttribute,它将当前身份提取出来并分配给当前用户。

IOwinContext context = actionContext.Request.GetOwinContext();
owinContext.Authentication.User = context.Get<ClaimsIdentity>("customdata:identity");
actionContext.RequestContext.Principal = owinContext.Authentication.User;

【讨论】:

    【解决方案3】:

    批处理的子请求在单独的线程中执行,并在这些请求中失去身份验证主体。

    在您的DelegatingHandler 中试试这个。

    var principal = new ClaimsPrincipal(identity);
    
    System.Threading.Thread.CurrentPrincipal = principal;
    if (System.Web.HttpContext.Current != null) {
        System.Web.HttpContext.Current.User = principal;
    }
    
    // Detect bearer token and build the identity above.
    IOwinContext owinContext = request.GetOwinContext();
    owinContext.Authentication.User = principal;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多