C# PowerShell 无法仅在 Web 应用程序中连接到 AzureAD

Posted

技术标签:

【中文标题】C# PowerShell 无法仅在 Web 应用程序中连接到 AzureAD【英文标题】:C# PowerShell Failed to connect to AzureAD in web app only 【发布时间】:2021-12-24 09:12:57 【问题描述】:

我使用以下 C# 代码运行 PowerShell 脚本以连接到 Azure AD。 PS 脚本在 PS ISE 中运行良好。 C# 代码在控制台应用程序中运行良好。详细输出显示与帐户、环境、租户 ID 相关信息的成功连接

当相同的 C# 代码作为代码在我的 Web 应用程序中运行时,powershell.Invoke() 步骤需要 30 秒才能返回并且无法连接到 AzureAD。错误如下所示。

我已验证导入 AzureAD 模块、创建 $UserName、$Password 和 $Credential 变量的步骤是否有效。

private void ConnectAzureAD()

    string PSModuleName = "C:\\PowerShellModules\\AzureAD";
    string loginName = "myID@mydomain.com";
    string loginPwd = "myPassword";

    PowerShell powershell = PowerShell.Create();
    try
    
        powershell.AddScript("Import-Module -Name '" + PSModuleName + "' -Force");
        powershell.AddScript("$UserName = '" + loginName + "'");
        powershell.AddScript("$Password = ConvertTo-SecureString '" + loginPwd + "'-AsPlainText -Force -Verbose");
        powershell.AddScript("$Credential = New-Object System.Management.Automation.PSCredential $UserName, $Password -Verbose");
        powershell.AddScript("Connect-AzureAD -Credential $Credential -Verbose");
        Collection<PSObject> PSOutput = powershell.Invoke();
    
    catch (Exception ex)
    
    

Powershell.Streams.Verbose:

Performing the operation "Connect-AzureAD" on target "Establishing a PowerShell session connected to 0 environment.".
    InvocationInfo: Command = Connect-AzureAD
    Message: "Performing the operation \"Connect-AzureAD\" on target \"Establishing a PowerShell session connected to 0 environment.\"."
    PipelineIterationInfo: Count = 2

Powershell.Streams.Error:

One or more errors occurred.: Object reference not set to an instance of an object.
    CategoryInfo: AuthenticationError: (:) [Connect-AzureAD], AadAuthenticationFailedException
    ErrorDetails: null
    Exception: "One or more errors occurred.: Object reference not set to an instance of an object."
    FullyQualifiedErrorId: "Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD"
    InvocationInfo: Command = Connect-AzureAD
    PipelineIterationInfo: Count = 2
    ScriptStackTrace: "at <ScriptBlock>, <No file>: line 1"
    TargetObject: null

One or more errors occurred.
    CategoryInfo: AuthenticationError: (:) [Connect-AzureAD], AggregateException
    ErrorDetails: null
    Exception: Count = 1
    FullyQualifiedErrorId: "Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD"
    InvocationInfo: Command = Connect-AzureAD
    PipelineIterationInfo: Count = 2
    ScriptStackTrace: "at <ScriptBlock>, <No file>: line 1"
    TargetObject: null

Object reference not set to an instance of an object.
    CategoryInfo: AuthenticationError: (:) [Connect-AzureAD], NullReferenceException
    ErrorDetails: null
    Exception: "Object reference not set to an instance of an object."
    FullyQualifiedErrorId: "Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD"
    InvocationInfo: Command = Connect-AzureAD
    PipelineIterationInfo: Count = 2
    ScriptStackTrace: "at <ScriptBlock>, <No file>: line 1"
    TargetObject: null

One or more errors occurred.: Object reference not set to an instance of an object.
    CategoryInfo: NotSpecified: (:) [Connect-AzureAD], AadAuthenticationFailedException
    ErrorDetails: null
    Exception: "One or more errors occurred.: Object reference not set to an instance of an object."
    FullyQualifiedErrorId: "Microsoft.Open.Azure.AD.CommonLibrary.AadAuthenticationFailedException,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD"
    InvocationInfo: Command = Connect-AzureAD
    PipelineIterationInfo: Count = 0
    ScriptStackTrace: "at <ScriptBlock>, <No file>: line 1"
    TargetObject: null

【问题讨论】:

您能否在 connect-AzureAd 命令中调用 $Credential.password.MakeReadOnly() 之前尝试调用它,然后在凭据之前和 connect-AzureAd 之后检查 $Credential.Password.Length。 【参考方案1】: 调用后密码凭据对象可能已被清除 出于安全原因,在 Azure Active Directory 中。 要通过调用 connect-azuread 调用来重新使用密码,您应该 在 cmdlet 调用之前将其设为只读。

解决方法:

    请先尝试调用 $Credential.password.MakeReadOnly() 在 connect-AzureAd 命令中调用它,然后检查 $Credential.Password.Length 在凭据之前和之后 连接 AzureAd。

例子:

$Credential.Password.Length
...
$Credential.password.MakeReadOnly()
Connect-AzureAD -Credential $Credential
$Credential.Password.Length

(或) 2. 通话时尝试复制原密码

$Credential = New-Object System.Management.Automation.PSCredential($Username, $Password.Copy())
    另外请阅读adding-a-credential-parameter下的要点 看看是否可以添加 ValidateNotNull() 属性来检查 凭据。

如果问题仍然存在,可能是由于 .net 或 c# 代码版本。尝试将其升级到最新版本。

【讨论】:

感谢您对此进行调查。我尝试了(1)和(2)。密码变量长度前后保持不变,我仍然得到相同的错误。控制台应用程序和 Web 应用程序都使用 .NET 框架 4.6.1 并使用相同的 Visual Studio IDE 编译。由于代码在控制台应用程序中运行良好,我认为 Web 应用程序失败的根本原因与 .NET 框架无关。

以上是关于C# PowerShell 无法仅在 Web 应用程序中连接到 AzureAD的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 Web 平台安装程序 API 的 Powershell 仅在 64 位机器上获取 x86 安装程序

从 PowerShell 调用时无法在 dll 中转换透明代理,但在 C# 控制台应用程序中成功

从 C# 应用程序的脚本中调用 PowerShell 函数

无法从 C# 调用 Powershell 函数

我的 PowerShell 脚本仅在从 ISE 运行时才有效

在 C# 中无法获取 PowerShell 命令的结果