C# 在ODataController中使用服务引用无法在IIS上工作

C# 在ODataController中使用服务引用无法在IIS上工作,c#,.net,iis,odata,C#,.net,Iis,Odata,我有一个ODataController作为MEF插件实现。此控制器在启动时从服务器应用程序加载。我在服务器应用程序中创建了另外3个ODataController,允许获取当前用户的Id、权限和角色(从ServerApplicationContext获取的信息)。从这些控制器中创建了一个服务引用,它允许将插件与服务器应用程序解耦,因此我不需要在插件中引用ServerApplicationContext。 在插件/扩展中,服务引用将按如下方式使用(实际上封装在静态类的方法中->服务在工作时将注入un

我有一个ODataController作为MEF插件实现。此控制器在启动时从服务器应用程序加载。我在服务器应用程序中创建了另外3个ODataController,允许获取当前用户的Id、权限和角色(从ServerApplicationContext获取的信息)。从这些控制器中创建了一个服务引用,它允许将插件与服务器应用程序解耦,因此我不需要在插件中引用ServerApplicationContext。 在插件/扩展中,服务引用将按如下方式使用(实际上封装在静态类的方法中->服务在工作时将注入unity):

只要应用程序不直接从VS2013运行IIS express,它就可以正常工作。一旦应用程序部署到独立IIS,从插入式控制器对服务引用的调用就会引发异常:

Microsoft.LightSwitch.Server: Unable to authenticate.  Access is denied.
  at Microsoft.LightSwitch.Utilities.ServerGenerated.Internal.ServerApplicationContextFactoryCore.AuthenticateUser()
  at Microsoft.LightSwitch.Server.ServerApplicationContextFactory.CreateContext(ServerApplicationContextCreationOptions options)
  at Microsoft.LightSwitch.Framework.Server.ServerApplicationContext`3.CreateContext()
  at LightSwitchApplication.Controllers.CurrentUserPermissionsController.GetCurrentUserPermissions(ODataQueryOptions`1 queryOptions)
Microsoft.Data.Services.Client: An error occurred while processing this request.
  at System.Data.Services.Client.DataServiceRequest.Execute[TElement](DataServiceContext context, QueryComponents queryComponents)
  at System.Data.Services.Client.DataServiceQuery`1.Execute()
  at System.Data.Services.Client.DataServiceQuery`1.GetEnumerator()
  at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
  at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
  at ODataExtensions.CurrentUserDataHelper.GetPermissionsOfCurrentUser()
  at ODataExtensions.CurrentUserDataHelper.HasCurrentUserPermission(String permissionId)
  at ODataExtensions.Controllers.HealthChecksController.<GetHealthChecks>d__2.MoveNext()
Microsoft.LightSwitch.Server:无法进行身份验证。访问被拒绝。
在Microsoft.LightSwitch.Utilities.ServerGenerated.Internal.ServerApplicationContextFactoryCore.AuthenticateUser()中
在Microsoft.LightSwitch.Server.ServerApplicationContextFactory.CreateContext(ServerApplicationContextCreationOptions)中
位于Microsoft.LightSwitch.Framework.Server.ServerApplicationContext`3.CreateContext()
在LightSwitchApplication.Controller.CurrentUserPermissionsController.GetCurrentUserPermissions(ODataQueryOptions`1查询选项)
Microsoft.Data.Services.Client:处理此请求时出错。
在System.Data.Services.Client.DataServiceRequest.Execute[TElement](DataServiceContext上下文,QueryComponents QueryComponents)
位于System.Data.Services.Client.DataServiceQuery`1.Execute()
在System.Data.Services.Client.DataServiceQuery`1.GetEnumerator()中
位于System.Collections.Generic.List`1..ctor(IEnumerable`1集合)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
在ODataExtensions.CurrentUserDataHelper.GetPermissionsOfCurrentUser()上
在ODataExtensions.CurrentUserDataHelper.HasCurrentUserPermissionId处
在ODataExtensions.Controllers.HealthChecksController.d_u2.MoveNext()中

重要提示:服务引用的URL已正确配置。用于获取当前用户信息的ODataController可以访问,如果直接访问,则返回正确的数据。一旦通过服务引用调用它们,就会发生上述错误。

以下代码的问题是,DefaultCredentials表示运行应用程序的当前安全上下文的系统凭据

Contracts.CurrentUserData.Administration _administrationService = new Contracts.CurrentUserData.Administration(new Uri(ConfigurationManager.AppSettings["A.Key"]));
_administrationService.Credentials = CredentialCache.DefaultCredentials;
_administrationService.CurrentUsers.ToList().First().Identity
在IIS Express上,应用程序正在管理员的安全上下文中运行—与我用于本地测试的用户相同。在独立IIS实例上,应用程序在用户
IIS APPPOOL\DefaultAppPool
的安全上下文中运行

解决方案

为了解决这个问题,我不得不模拟服务引用调用。以下代码是从ODataController调用的,因此可以从
HttpContext
获取模拟的用户标识

    public static String GetCurrentUserId()
    {
        var administrationService = GetServiceReferenceInstance();
        var identity = (WindowsIdentity)HttpContext.Current.User.Identity;
        administrationService.Credentials = CredentialCache.DefaultCredentials;
        using (var impersonationContext = identity.Impersonate())
        {
            return administrationService.CurrentUsers.ToList().First().Identity;
        }
    }

    private static Contracts.CurrentUserData.Administration GetServiceReferenceInstance()
    {
        return new Contracts.CurrentUserData.Administration(new Uri(ConfigurationManager.AppSettings["AKey"]));
    }
    public static String GetCurrentUserId()
    {
        var administrationService = GetServiceReferenceInstance();
        var identity = (WindowsIdentity)HttpContext.Current.User.Identity;
        administrationService.Credentials = CredentialCache.DefaultCredentials;
        using (var impersonationContext = identity.Impersonate())
        {
            return administrationService.CurrentUsers.ToList().First().Identity;
        }
    }

    private static Contracts.CurrentUserData.Administration GetServiceReferenceInstance()
    {
        return new Contracts.CurrentUserData.Administration(new Uri(ConfigurationManager.AppSettings["AKey"]));
    }