首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >定义接受PSCredential对象的Powershell函数,但如果它为null,则不会提示吗?

定义接受PSCredential对象的Powershell函数,但如果它为null,则不会提示吗?
EN

Stack Overflow用户
提问于 2016-05-04 17:53:51
回答 2查看 4K关注 0票数 3

我有一个接受PSCredential对象的Powershell函数。如果PSCredential为null,我希望自己在函数中特别处理这个问题。但是,最终发生的情况是我得到了一个PSCredential提示符(与运行Get-Credential时相同)。

在下面的脚本中,我为Credential参数集设置了所需的参数,并希望用[AllowNull()]使其为空,但这并没有阻止提示符出现。

这是我的功能:

代码语言:javascript
运行
复制
<#
.description
Create a new Connection String Builder object
.parameter existingCSB
Use the passed CSB as the base, but allow it to be overridden.
.parameter property
Hashtable containing named properties for a connection string builder.
Will override values on -existingCSB.
.parameter credential
Use these credentials. Will override values on -existingCSB and any values
passed as -property.
NOTE: If this parameter is null, or if EITHER the username OR password in
the credential is an empty string, use a trusted connection aka 
integrated security instead
.parameter username
Use this username. Will override values on -existingCSB and any values
passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a
trusted connection / integrated security instead
.parameter password
Use this password. Can be a string or a SecureString object. Will override
values on -existingCSB and any values passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a
trusted connection / integrated security instead
#>
function New-DbConnectionStringBuilder {
    [cmdletbinding(DefaultParameterSetName="NoCredential")] param(
        [System.Data.Common.DbConnectionStringBuilder] $existingCSB,

        [Hashtable] $property,

        [Parameter(Mandatory=$true, ParameterSetName="Credential")]
        [AllowNull()] [System.Management.Automation.PSCredential] $credential,

        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        [AllowEmptyString()] [string] $username,

        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        [AllowNull()] $password
    )
    $newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
    if ($existingCSB.Keys.Count -gt 0) {
        $existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
    }
    if ($property.Keys.Count -gt 0) {
        $property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
    }

    if ($PsCmdlet.ParameterSetName -notmatch "NoCredential") {
        if ($credential) {
            $username = $credential.UserName
            $password = $credential.Password
        }
        if ($password -and $password.GetType().FullName -eq "System.Security.SecureString") {
            $password = Decrypt-SecureString $password
        }

        if ($username -and $password) {
            $newDbCSB["Uid"] = $username
            $newDbCSB["Pwd"] = $password
            $newDbCSB.Remove("Trusted_Connection") | Out-Null
        }
        else {
            $newDbCSB["Uid"] = $null
            $newDbCSB["Pwd"] = $null
            $newDbCSB["Trusted_Connection"] = "yes"
        }
    }

    return $newDbCSB
}

下面是一些调用它的代码:

代码语言:javascript
运行
复制
$csb = New-DbConnectionStringBuilder -credential $null
Write-Host "UID: $($csb['Uid'])"
Write-Host "Trusted_Connection: $($csb['Trusted_Connection'])"

如果您感兴趣,我这么做的原因是为了与现有代码兼容。我们有一些脚本可以从签入Git的加密文件中获取凭据。如果没有凭据,则现有代码将返回$null作为应该使用集成安全性的指示。

概括起来,我想要的行为是:如果根本没有传递凭据,就不要向CSB添加凭据信息;如果凭据是传递的,而是$null,则使用集成安全性(也称为“可信连接”);如果凭据被传递,而不是null,则在CSB中使用它们。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-04 18:06:27

没有什么叫空值PSCredential-parameter。它将迫使您输入某种类型的凭据。最简单的解决方案是检查要传递给-Credential的输入,如果输入是$null,则将其替换为[pscredential]::Empty。例如。

代码语言:javascript
运行
复制
$creds = $null
if($creds -eq $null) { $creds = ([System.Management.Automation.PSCredential]::Empty) }
$csb = New-DbConnectionStringBuilder -credential $creds

此外,还可以使用以下方法简化密码部分:

代码语言:javascript
运行
复制
if ($credential) {
    $username = $credential.UserName
    $password = $credential.GetNetworkCredential().Password
}

修改后的解决方案:

代码语言:javascript
运行
复制
function New-DbConnectionStringBuilder {
    [cmdletbinding(DefaultParameterSetName="NoCredential")] param(
        [System.Data.Common.DbConnectionStringBuilder] $existingCSB,

        [Hashtable] $property,

        [Parameter(Mandatory=$true, ParameterSetName="Credential")]
        [System.Management.Automation.PSCredential] $credential,

        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        [string] $username,

        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        $password
    )

    $newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
    if ($existingCSB.Keys.Count -gt 0) {
        $existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
    }
    if ($property.Keys.Count -gt 0) {
        $property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
    }

    if($PsCmdlet.ParameterSetName -ne "NoCredential") {

        if ($PsCmdlet.ParameterSetName -eq "Credential" -and $credential -ne [System.Management.Automation.PSCredential]::Empty) {
            $username = $credential.UserName.Split("\")[-1]
            $password = $credential.GetNetworkCredential().Password
        }

        if ($username -and $password) {
            $newDbCSB["Uid"] = $username
            $newDbCSB["Pwd"] = $password
            $newDbCSB.Remove("Trusted_Connection") | Out-Null
        }
        else {
            $newDbCSB["Uid"] = $null
            $newDbCSB["Pwd"] = $null
            $newDbCSB["Trusted_Connection"] = "yes"
        }

    }

    $newDbCSB
}

演示:

代码语言:javascript
运行
复制
Write-host
Write-host Null creds
Write-host
$creds = $null

if($creds -eq $null) { $creds = ([System.Management.Automation.PSCredential]::Empty) }
$csb = New-DbConnectionStringBuilder -credential $creds

Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"

Write-host
Write-host Creds
Write-host
$creds = New-Object System.Management.Automation.PSCredential "frode", (ConvertTo-SecureString -String "lol" -AsPlainText -Force)

if($creds -eq $null) { $creds = ([System.Management.Automation.PSCredential]::Empty) }
$csb = New-DbConnectionStringBuilder -credential $creds

Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"

Write-host
Write-host Username and password
Write-host
$csb = New-DbConnectionStringBuilder -username frode -password pass

Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"

Write-host
Write-host Nothing
Write-host
$csb = New-DbConnectionStringBuilder

Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"

输出:

代码语言:javascript
运行
复制
Null creds

UID: 
pass: 
Trusted_Connection: yes

Creds

UID: frode
pass: lol
Trusted_Connection: 

Username and password

UID: frode
pass: pass
Trusted_Connection: 

Nothing

UID: 
pass: 
Trusted_Connection:

编辑:实际上,您可以使用[object]参数来接受空值凭据,并验证它是否是脚本中的PSCredential-object,但是在编写New-DbConnectionStringBuilder -Credential "frode"时将失去提示输入密码的好处。

我更喜欢上面的解决方案,并验证调用方脚本中的输入(修复空值)。这样,函数仍然是“最佳实践”,用户(您)将负责清理/验证输入,就像您应该做的那样。

代码语言:javascript
运行
复制
function New-DbConnectionStringBuilder {
    [cmdletbinding(DefaultParameterSetName="NoCredential")] param(
        [System.Data.Common.DbConnectionStringBuilder] $existingCSB,

        [Hashtable] $property,

        [Parameter(ParameterSetName="Credential")]
        [object] $credential,

        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        [string] $username,

        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        $password
    )

    #Validate credential-type
    if($credential -ne $null -and $credential -isnot [System.Management.Automation.PSCredential]) { Write-Error -Message "credential parameter is not null or PSCredential" -Category InvalidArgument -ErrorAction Stop }

    $newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
    if ($existingCSB.Keys.Count -gt 0) {
        $existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
    }
    if ($property.Keys.Count -gt 0) {
        $property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
    }

    Write-Host ($credential -eq [System.Management.Automation.PSCredential]::Empty)

    if($PsCmdlet.ParameterSetName -ne "NoCredential") {

        if ($credential -ne $null -and $credential -ne [System.Management.Automation.PSCredential]::Empty) {
            $username = $credential.UserName.Split("\")[-1]
            $password = $credential.GetNetworkCredential().Password
        }

        if ($username -and $password) {
            $newDbCSB["Uid"] = $username
            $newDbCSB["Pwd"] = $password
            $newDbCSB.Remove("Trusted_Connection") | Out-Null
        }
        else {
            $newDbCSB["Uid"] = $null
            $newDbCSB["Pwd"] = $null
            $newDbCSB["Trusted_Connection"] = "yes"
        }

    }

    $newDbCSB
}

$creds = $null
$csb = New-DbConnectionStringBuilder -credential $creds

Write-Host "UID: $($csb["Uid"])"
write-host "pass: $($csb["pwd"])"
Write-Host "Trusted_Connection: $($csb["Trusted_Connection"])"
票数 4
EN

Stack Overflow用户

发布于 2016-05-04 21:50:16

通过简单地从参数中省略类型注释,我就能够接近我想要的东西了。当我这样做时,Powershell不会启动PSCredential弹出,我只需处理函数中的所有内容。

也许不是最优雅的解决方案,但它确实有效。

这是我的密码:

代码语言:javascript
运行
复制
<#
.description
Create a new Connection String Builder object
.parameter existingCSB
Use the passed CSB as the base, but allow it to be overridden.
.parameter property
Hashtable containing named properties for a connection string builder. Will override values on -existingCSB.
.parameter credential
Use these credentials. Will override values on -existingCSB and any values passed as -property.
NOTE: If this parameter is null, or if EITHER the username OR password in the credential is an empty string, use a trusted connection / integrated security instead
.parameter username
Use this username. Will override values on -existingCSB and any values passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a trusted connection / integrated security instead
.parameter password
Use this password. Can be a string or a SecureString object. Will override values on -existingCSB and any values passed as -property
NOTE: If EITHER the username OR password is null or an empty string, use a trusted connection / integrated security instead
#>
function New-DbConnectionStringBuilder {
    [cmdletbinding(DefaultParameterSetName="NoCredential")] param(
        [System.Data.Common.DbConnectionStringBuilder] $existingCSB,

        [Hashtable] $property,

        # Do not give a type, so that this may be $null or a PSCredential object
        # NOTE that there is no such thing as a null PSCredential object - the closest thing is [PSCredential]::Empty
        [Parameter(Mandatory=$true, ParameterSetName="Credential")]
        # [System.Management.Automation.PSCredential]
        [AllowNull()] $credential,

        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        [AllowEmptyString()] [string] $username,

        # Do not give a type, so that this might be a string or a SecureString
        [Parameter(Mandatory=$true, ParameterSetName="UserPass")]
        [AllowNull()] $password
    )

    $newDbCSB = New-Object System.Data.Common.DbConnectionStringBuilder $true
    if ($existingCSB.Keys.Count -gt 0) {
        $existingCSB.Keys |% { $newDbCSB[$_] = [String]::Copy($existingCSB[$_]) }
    }
    if ($property.Keys.Count -gt 0) {
        $property.Keys |% { $newDbCSB[$_] = [String]::Copy($property[$_]) }
    }

    if ($PsCmdlet.ParameterSetName -eq "Credential") {
        if ($credential) {
            # Note that we assume this is a PSCredential object, but it could be anything with a string UserName property and a string or SecureString Password property
            $tmpUser = $credential.UserName
            $tmpPass = $credential.Password
        }
        else {
            $tmpUser = $tmpPass = $null
        }
    }
    elseif ($PsCmdlet.ParameterSetName -eq "UserPass") {
        $tmpUser = $username
        $tmpPass = $password
    }

    if ($PsCmdlet.ParameterSetName -notmatch "NoCredential") {
        if ($tmpPass -and $tmpPass.GetType().FullName -eq "System.Security.SecureString") {
            $tmpPass = Decrypt-SecureString $tmpPass
        }

        if ($tmpUser -and $tmpPass) {
            $newDbCSB["Uid"] = $tmpUser
            $newDbCSB["Pwd"] = $tmpPass
            $newDbCSB.Remove("Trusted_Connection") | Out-Null
        }
        else {
            $newDbCSB["Uid"] = $null
            $newDbCSB["Pwd"] = $null
            $newDbCSB["Trusted_Connection"] = "yes"
        }
    }

    return $newDbCSB
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37034752

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档