【发布时间】:2021-08-10 08:35:33
【问题描述】:
谁能建议如何在远程域上验证凭据?
我的环境有多个域,它们之间没有定义信任关系。 我有一个 Powershell 脚本,它需要访问驻留在另一个域中的服务器上的共享文件夹,这显然需要身份验证。在访问它之前,我需要验证凭据以避免锁定(该脚本可以针对多个服务器运行)。
过去我使用过这个wonderful script,它使用当前域进行验证,但我无法让它在远程域上工作。 我试过这是(从上面的链接稍微修改的脚本):
function Test-Cred {
[CmdletBinding()]
[OutputType([String])]
Param (
[Parameter(
Mandatory = $false,
ValueFromPipeLine = $true,
ValueFromPipelineByPropertyName = $true
)]
[Alias(
'PSCredential'
)]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credentials
)
$Domain = $null
$Root = $null
$Username = $null
$Password = $null
If($Credentials -eq $null)
{
Try
{
$Credentials = Get-Credential "domain\$env:username" -ErrorAction Stop
}
Catch
{
$ErrorMsg = $_.Exception.Message
Write-Warning "Failed to validate credentials: $ErrorMsg "
Pause
Break
}
}
# Checking module
Try
{
# Split username and password
$Username = $credentials.username
$Password = $credentials.GetNetworkCredential().password
# Get Domain
###$Root = "LDAP://" + ([ADSI]'').distinguishedName
$Root = "LDAP://DC=remote_domain,DC=com" ### statically define the remote domain
$Domain = New-Object System.DirectoryServices.DirectoryEntry($Root,$UserName,$Password)
}
Catch
{
$_.Exception.Message
Continue
}
If(!$domain)
{
Write-Warning "Something went wrong"
}
Else
{
If ($domain.name -ne $null)
{
return "Authenticated"
}
Else
{
$Domain ### diagnosing the error
return "Not authenticated"
}
}
}
我收到以下错误:
format-default : The following exception occurred while retrieving member "distinguishedName": "The user name or
password is incorrect.
"
+ CategoryInfo : NotSpecified: (:) [format-default], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMember,Microsoft.PowerShell.Commands.FormatDefaultCommand
用户名/密码 100% 正确。 谢谢
编辑 1
我找到了以下blog post,其中介绍了如何使用 .Net 程序集处理 Active Directory。以下效果很好
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
#store credentials (of account with appropriate permissions)
$creds = Get-Credential
#set the domain name
$dn = 'contoso.com'
#Create the principal context object (so to say connect to a domain with the credentials provided)
$pc = [System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::`
Domain,$dn,$($creds.UserName),$($creds.GetNetworkCredential().Password))
我假设我可以在 If 语句中使用它来实现我所需要的。诚然,我不知道 .Net 的方式,它有点吓人,但我必须学习它。
编辑 2
这是我拼凑的:
Function Test-Cred
{
[CmdletBinding()]
[OutputType([String])]
Param (
[Parameter(
Mandatory = $false,
ValueFromPipeLine = $true,
ValueFromPipelineByPropertyName = $true
)]
[Alias(
'PSCredential'
)]
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credentials
)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
# Checking module
$Validated = [System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain,'remote_domain',$($Credentials.UserName),$($Credentials.GetNetworkCredential().Password))
If ($Validated.ConnectedServer)
{
Return "Authenticated"
}
Else
{
Return "Not authenticated"
}
}
有什么反馈吗?
编辑 3
嗯,EDIT 2 不适用于 Powershell 4,grrr
Method invocation failed because [System.DirectoryServices.AccountManagement.PrincipalContext] dies not contain method named 'new'
我必须让它像这样工作:
$ContextType = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$ContextName = 'target_domain.com'
$Validated = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ContextType, $ContextName, $($Credentials.UserName),$($Credentials.GetNetworkCredential().Password)
【问题讨论】:
-
请注意,不需要第一个 try/catch 块。 Get-Credential 不验证任何内容。它只是创建一个凭证对象,其中包含一个用户名字符串和一个安全字符串密码以供以后使用。它没有在该 try 块中进行测试、验证、使用等。
-
好点!谢谢
标签: powershell active-directory ldap