【问题标题】:System.DirectoryServices.AccountManagement.UserPrincipal - localhost but not iisSystem.DirectoryServices.AccountManagement.UserPrincipal - localhost 但不是 iis
【发布时间】:2012-06-23 16:48:30
【问题描述】:

为什么下面的代码在我运行 Web 应用程序 localhost 时可以正常工作,但在我将其安装到 IIS 服务器时却不行?

using (HostingEnvironment.Impersonate())
{
    UserPrincipal activeUser = UserPrincipal.Current;
    String activeUserSid = activeUser.Sid.ToString();
    String activeUserUPN = activeUser.UserPrincipalName;
}

请不要建议我坚持使用 HttpContext.Current.User,因为它不提供对 SID 或 UPN 的访问而无需额外调用 Active Directory。

Web 应用程序将由来自三个不同域的 Windows 身份验证用户使用,Web 服务器托管在第四个域中。应用程序池配置为在 NetworkService 身份下运行,并且 Web 应用配置将身份模拟设置为 true。

在 IIS 上运行时的错误信息是:

Page_Load() 中的错误:UserPrincipal.Current。
System.InvalidCastException:无法转换类型的对象 'System.DirectoryServices.AccountManagement.GroupPrincipal' 键入 'System.DirectoryServices.AccountManagement.UserPrincipal'。
在 System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext 上下文,IdentityType identityType,字符串 identityValue)
在 System.DirectoryServices.AccountManagement.UserPrincipal.get_Current()
在 webapp.Details.Default.Page_Load(Object sender, EventArgs e)

编辑: 尝试了以下两种方法,不幸的是得到了同样的错误。

UserPrincipal userPrincipal = UserPrincipal.Current;
Response.Write(userPrincipal.Name);
Principal userOrGroup = UserPrincipal.Current;
Response.Write(userOrGroup.Name);

【问题讨论】:

    标签: asp.net impersonation userprincipal


    【解决方案1】:

    似乎需要其他方法来确定用户。
    这里来自 msdn 的属性描述:
    "获取一个用户主体对象,该对象代表线程正在其下运行的当前用户。"
    因此,UserPrincipal.Current 返回运行 IIS 的用户。

    http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.userprincipal.aspx

    【讨论】:

    • 我认为你是对的。这也不起作用... var wi = HttpContext.Current.User.Identity as WindowsIdentity;使用 (wi.Impersonate()) { UserPrincipal up = UserPrincipal.Current; activeUserUPN = up.UserPrincipalName; activeUserSid = up.Sid.ToString(); }
    • IIS中的“当前运行线程的用户”很可能是IIS App Pool Identity;但是当在您的 PC 上的 Visual Studio、Casini 或 IIS Express 中运行时,它会像您一样运行。在这种情况下,您的身份由请求页面的客户端和本地运行的开发服务器共享。
    【解决方案2】:

    我在部署 UserPrincipal.Current 时遇到了很多问题,但仍然不完全明白为什么。

    我最终使用了 PrincipalSearcher,并创建了以下函数来做我认为 UserPrincipal.Current 正在做的事情。

    private UserPrincipal GetActiveDirectoryUser(string userName)
    {
        using(var ctx = new PrincipalContext(ContextType.Domain))
        using(var user = new UserPrincipal(ctx) { SamAccountName = userName})
        using(var searcher = new PrincipalSearcher(user))
        {
            return searcher.FindOne() as UserPrincipal;
        }
    }
    

    我将 System.Web.HttpContext.Current.User.Identity.Name 作为用户名传递给该方法。

    【讨论】:

    • 我收到此错误:System.ObjectDisposedException: Cannot access a disposed object. Object name: 'PrincipalContext'. at System.DirectoryServices.AccountManagement.PrincipalContext.CheckDisposed() at System.DirectoryServices.AccountManagement.PrincipalContext.get_ContextType() at System.DirectoryServices.AccountManagement.Principal.get_Name() at System.String.Concat(Object[] args) at Admin_Click(Object sender, EventArgs e)
    • 我在 MVC 应用程序中尝试了多种方法。 DirectoryEntry de = new DirectoryEntry("WinNT://" + Environment.UserDomainName + "/" + userId); string Username = de.Properties["fullName"].Value.ToString(); 然后我尝试了System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName; 然后尝试了您的解决方案,它是部署到我的生产服务器时唯一可以工作的解决方案......不知道为什么。都在本地工作...
    【解决方案3】:

    是的,这是因为由于多个 using 语句,您正在处理返回的 UserPrincipal 对象。从 using 语句中删除 'ctx',然后调用者负责处理返回的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-28
      • 1970-01-01
      • 2012-12-01
      • 2017-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-16
      相关资源
      最近更新 更多