我有一个作为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是可访问的,如果直接访问它们,则返回正确的数据。只要它们通过服务参考进行校准,就会发生上述错误。
答案 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"]));
}