Powershell UseDefaultCredentials不在远程会话中工作

时间:2015-03-10 05:16:53

标签: powershell

我正在尝试在远程计算机上运行Invoke-WebRequest命令。 我正在使用的帐户是两台计算机上的本地管理员。 如果我登录到远程计算机并运行 Invoke-WebRequest $url -UseDefaultCredentials,它完美无缺。

然而,当我跑步时 我本地计算机上的Invoke-Command -ComputerName machineName -ScriptBlock { Invoke-WebRequest "the path" -UseDefaultCredentials },它给了我401 - 未经授权:由于凭据无效而拒绝访问。 我也试过开始远程会话; Enter-PSSession -ComputerName machineName然后只运行Invoke-WebRequest "the path" -UseDefaultCredentials,但结果相同。

为什么会这样?远程运行时权限发生了哪些变化?如何在不提示输入密码且不将密码存储在脚本中的情况下解决这个问题?

1 个答案:

答案 0 :(得分:1)

在远程服务器上运行以下命令:Enable-WSManCredSSP -Role Server –Force

(看来你必须手动执行此操作;以下操作无效:

$remoteHosts | %{
    invoke-command -ComputerName $_ -Credential $cred -ScriptBlock {
        Enable-WSManCredSSP -Role Server –Force | out-null
    }
}

然后使用以下代码使本地计算机信任远程计算机,然后使用此信任来调用它。 注意:如果您希望在不同的域中呼叫远程计算机,请注释掉代码。

[string[]]$remoteHosts = @('server1','server2')

$remoteHosts | %{Enable-WSManCredSSP -Role Client -DelegateComputer $_ -Force} | out-null

#if dealing with remote domains
#$trustedBefore = (Get-Item WSMan:\localhost\Client\TrustedHosts).value
#winrm set winrm/config/client ("@{{TrustedHosts='{0}'}}" -f (($remoteHosts + $remoteHosts) -join ',')) | out-null
$cred = get-credential
$remoteHosts | %{
    InvokeCommand -ScriptBlock {
        invoke-webrequest 'https://myUrl/' -UseDefaultCredentials | select StatusCode 
    } -Computer $_ -Credential $cred -Authentication Credssp
}
#winrm set winrm/config/client ("@{{TrustedHosts='{0}'}}" -f $trustedBefore) | out-null

参考:第二跳安全问题     http://blogs.technet.com/b/heyscriptingguy/archive/2012/11/14/enable-powershell-quot-second-hop-quot-functionality-with-credssp.aspx

参考:不同域中的远程计算机 https://technet.microsoft.com/en-us/magazine/ff700227.aspx

注意:您可能还发现远程服务器位于不同的PS版本上(即较旧的操作系统默认具有PS2)。 如果你得到了,下面是PS2 Invoke-WebRequest的粗略近似值(需要包含在脚本块中)

function Invoke-PS2WebRequest {
    param(
        $Uri
    )
    try {
        $request = [System.Net.HttpWebRequest]::Create($Uri)
        $request.UseDefaultCredentials = $true
        $request.PreAuthenticate = $true
        $resp = $request.GetResponse()
        $reqstream = $resp.GetResponseStream()
        $sr = new-object System.IO.StreamReader $reqstream
        $result = $sr.ReadToEnd()
        write-output (new-object -TypeName PSObject -Property @{ 
            StatusDescription = $resp.StatusDescription
            StatusCode = [int]$resp.StatusCode
            Content = $result
        })
    } catch {
        write-output (new-object -TypeName PSObject -Property @{ 
            StatusDescription = 'ERROR'
            StatusCode = [int]([regex]::matches($_.exception.message, "(?<=\()[\d]{3}").Value)
            Content = $_.exception.message
        })        
    }
}