我想针对域控制器验证一组凭据.例如:
Username: STACKOVERFLOW\joel
Password: splotchy
Run Code Online (Sandbox Code Playgroud)
很多人建议查询Active Directory.如果抛出异常,那么您知道凭据无效 - 正如此stackoverflow问题中所建议的那样.
您不仅要对域帐户进行身份验证,还要进行隐式授权检查.也就是说,您正在使用模拟令牌从AD中读取属性.如果其他有效帐户无权从AD读取,该怎么办?默认情况下,所有用户都具有读取权限,但可以将域策略设置为禁用受限帐户(和/或组)的访问权限.
绑定AD会产生严重的开销,必须在客户端加载AD架构缓存(DirectoryServices使用的ADSI提供程序中的ADSI缓存).这既是网络又是AD服务器,消耗资源 - 而且对于像验证用户帐户这样的简单操作来说太昂贵了.
您依赖于非例外情况的异常失败,并假设这意味着无效的用户名和密码.然后,其他问题(例如,网络故障,AD连接故障,内存分配错误等)被错误地表示为身份验证失败.
其他人建议使用LogonUser()API函数.这听起来不错,但不幸的是,调用用户有时需要一个权限,通常只给操作系统本身:
调用LogonUser的进程需要SE_TCB_NAME权限.如果调用进程没有此权限,LogonUser将失败,GetLastError将返回ERROR_PRIVILEGE_NOT_HELD.
在某些情况下,调用LogonUser的进程还必须启用SE_CHANGE_NOTIFY_NAME权限; 否则,LogonUser失败,GetLastError返回ERROR_ACCESS_DENIED.作为管理员组成员的本地系统帐户或帐户不需要此权限.默认情况下,为所有用户启用SE_CHANGE_NOTIFY_NAME,但某些管理员可能会为所有用户禁用它.
省高院" 法案作为操作系统的一部分 "特权是不是你想要做无可奈何的东西-作为微软在一份指出知识库文章:
...调用LogonUser的进程必须具有SE_TCB_NAME权限(在用户管理器中,这是" 作为操作系统的一部分 "权限).SE_TCB_NAME权限非常强大, 不应授予任何任意用户,以便他们可以运行需要验证凭据的应用程序.
此外,LogonUser()如果指定了空密码,则调用将失败.
验证一组域凭据的正确方法是什么?
我碰巧是从托管代码调用,但这是一个普通的Windows问题.可以假设客户已安装.NET Framework 2.0.
在调用时InitializeSecurityContext,我传递给TargetName参数的值是多少?
我正在调用这个函数InitializeSecurityContext:
InitializeSecurityContextA(
@pAS.hcred, //[in] credentials
phContext, //[in] optional] Context handle structure
pszTargetName, //[in, optional] Target name
0, //[in] context requirements
0, //[in] reserved1, must be zero
SECURITY_NATIVE_DREP, //[in] target data representation
pInput, //[in] optional] SecBufferDescription
0, //[in] reserved2, must be zero
@pAS.hctxt, //[in, out] pointer to context handle structure
@OutBuffDesc, //[in, out] pointer to SecBufferDesc
ContextAttributes, //[out] context attributes
@lifetime); //[out] expiration timestamp
Run Code Online (Sandbox Code Playgroud)
我传递给pszTargetName谁?
我试过了
null: InitializeSecurityContextA(@pAS.hcred, phContext, …登录到Windows时,将缓存您的凭据.这允许您使用单点登录.如果您要浏览到另一台计算机,例如:
\\hydrogen
Run Code Online (Sandbox Code Playgroud)

系统不会提示您输入凭据.
Windows将采取您的:
并尝试自动验证您.有趣的是,如果您的工作站不在域上,这甚至可以工作.连接到服务器后,Windows将自动使用您的用户名和密码.如果你的:
你会自动进入.
美丽的照片:

这称为单点登录.您登录Windows一次,并且在您使用网络上的其他内容时,您的缓存凭据将用于验证您.
Chrome,Internet Explorer和Firefox也对此进行了修改.如果您需要登录到网站,并且服务器支持协商授权,服务器将向您发回一个指示,您应该尝试使用用户的Windows /域/ Kerberos凭据:
HTTP/1.1 401 Unauthorized
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
Date: Thu, 09 Jul 2015 14:35:58 GMT
Content-Length: 0
Run Code Online (Sandbox Code Playgroud)
然后,Chrome会获取您的缓存凭据,并且(经过一些中级魔法)将它们转发到Web服务器:
GET http://hr.woodglue.com HTTP/1.1
Host: hr.woodglue.com
Authorization: Negotiate YIIFzwYGKwYBBQUCoIIFwzCCBb....
Run Code Online (Sandbox Code Playgroud)

Microsoft在旧文章中讨论了Internet Explorer中的这种机制:
使用协商协议进行基于HTTP的跨平台认证
- 客户端调用
AcquireCredentialsHandle()并InitializeSecurityContext()与SPN一起构建从TGS/KDC请求会话票证的安全上下文.
我要提到的最后一点是服务器,Web服务器,工作站,文件服务器,不验证服务器的凭据,它们针对域控制器进行验证.您有许多域服务器的模糊森林,其中一个处理您的请求.
换句话说,您不会针对以下内容验证凭据:
\\uranium (域上的woodglue.com域控制器)您验证凭据: …