IIS在使用Windows身份验证时如何获取WindowsPrincipal上的数据?

huangapple go评论65阅读模式
英文:

How does IIS get data on WindowsPrincipal when using Windows Authentication?

问题

对于使用Windows身份验证的内部应用程序,我可以使用以下C#代码获取WindowsPrincipal对象:

var winPrincipal = (WindowsPrincipal)HttpContext.Current.User;

这些信息(包括用户的Sam名称和域组,这些信息包含在该对象中)是否直接从用户的计算机传递给IIS,还是IIS必须查询LDAP?

我发现从应用程序代码查询LDAP不是免费操作,所以我想知道如果IIS正在查询LDAP以构建WindowsPrincipal对象,是否会给请求增加一些额外开销,如果IIS没有查询LDAP,那么是否会引入安全问题,如果我只信任来自IIS的WindowsPrincipal对象而不查询LDAP(也就是说,攻击者是否可能在请求中添加他们实际上不在的组)?

英文:

For an internal application using Windows Authentication, I am able to get a WindowsPrincipal object in C# using this code:

var winPrincipal = (WindowsPrincipal)HttpContext.Current.User;

Is this information (including Sam name and domain groups the user is in, which is included on this object) communicated to IIS directly from the user's computer, or does IIS have to query LDAP?

I've found that Querying LDAP from application code is not a free operation, so I'm wondering if this adds some overhead to a request if IIS is querying LDAP to construct the WindowsPrincipal object, and if it's not querying LDAP then does that introduce any security issues if I just trust the WindowsPrincipal object from IIS without querying LDAP (i.e. could an attacker potentially add groups they aren't really in to their ticket on the request)?

答案1

得分: 1

Windows身份验证使用用户计算机的访问令牌,但服务器会验证其有效性。

身份验证组存储在令牌中,因此不需要发出LDAP请求。

如果您需要从用户帐户中获取不在令牌中的任何信息,那么您确实需要自己发出LDAP请求。最有效的方式是直接绑定到用户对象,使用已经拥有的SID:

var identity = (WindowsIdentity)HttpContext.Current.User.Identity;

var user = new DirectoryEntry($"LDAP://<SID={identity.User.Value}>");

// 只请求要读取的属性。
// 如果省略此步骤,它将获取每个带有值的属性,
// 这是不必要的。
user.RefreshCache(new [] { "givenName", "sn" });

var firstName = user.Properties["givenName"].Value;
var lastName = user.Properties["sn"].Value;

如果您担心发出LDAP请求时的效率问题,我以前写过一篇讨论这个问题的文章:Active Directory:性能优化

英文:

Windows Authentication uses the access token from the user's computer, but the server does verify that it is valid.

The authentication groups are stored in the token, so that doesn't make an LDAP request.

If you need any information from the user's account that isn't stored in the token, then you do need to make an LDAP request yourself. The most efficient way is to bind directly to the user's object using the SID, which you already have:

var identity = (WindowsIdentity) HttpContext.Current.User.Identity;

var user = new DirectoryEntry($&quot;LDAP://&lt;SID={identity.User.Value}&gt;&quot;);

//Ask for only the attributes you want to read.
//If you omit this, it will end up getting every attribute with a value,
//which is unnecessary.
user.RefreshCache(new [] { &quot;givenName&quot;, &quot;sn&quot; });

var firstName = user.Properties[&quot;givenName&quot;].Value;
var lastName = user.Properties[&quot;sn&quot;].Value;

If you're worried about efficiency when making LDAP requests, I wrote an article a while ago that discusses that: Active Directory: Better performance

huangapple
  • 本文由 发表于 2023年6月5日 22:23:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76407412.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定