使用ODataController中的服务引用不能在IIS上工作

时间:2015-07-28 07:26:30

标签: c# .net iis odata

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

Contracts.CurrentUserData.Administration _administrationService = new Contracts.CurrentUserData.Administration(new Uri(ConfigurationManager.AppSettings["A.Key"]));
_administrationService.Credentials = CredentialCache.DefaultCredentials;
_administrationService.CurrentUsers.ToList().First().Identity

只要应用程序没有直接从VS2013运行IIS,它就能正常工作。一旦将应用程序部署到独立的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()

重要信息:已正确配置服务参考的URL。用于获取有关当前用户的信息的ODataControllers是可访问的,如果直接访问它们,则返回正确的数据。只要它们通过服务参考进行校准,就会发生上述错误。

1 个答案:

答案 0 :(得分:1)

以下代码的问题在于,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"]));
    }