Java ProcessBuilder 以管理员身份执行 PowerShell 脚本

问题描述 投票:0回答:1

我有一个以非管理员权限启动的 Java 应用程序。 我想从我的 Java 应用程序启动不同的 PowerShell 脚本。 PowerShell 脚本具有输入和输出参数。在脚本内部执行 PSRemoting 命令以控制其他 Windows PC。我需要以管理员身份从 Java 启动 PowerShell 脚本。在我的 Java 应用程序中,管理员用户和管理员密码是已知的。

启动 PowerShell 脚本、传递参数并返回返回值,到目前为止确实有效。但我还没有设法以管理员身份启动脚本。

      List<String> cmd = new ArrayList<>();
      cmd.add("powershell.exe");
      cmd.add("-ExecutionPolicy");
      cmd.add("Bypass");
      cmd.add("-File");
      cmd.add(tempScriptPath.toString());

      // Add the arguments for the PowerShell file
      Iterator<Map.Entry<String, JsonNode>> fields = jsonArgs.fields();
      while (fields.hasNext()) {
        Map.Entry<String, JsonNode> field = fields.next();
        String key = field.getKey();
        String value = field.getValue().asText(); // Get value as text

        // Add the key and value to the list
        cmd.add("-" + key);
        cmd.add(value);
      }


      ProcessBuilder pb = new ProcessBuilder(cmd);
      pb.redirectErrorStream(true); // Combine stdout and stderr

      // Start the process
      Process process = pb.start();

这是一个虚拟的 PowerShell 脚本:

param (
    [string]$ip
)
Write-Output "PS INFO: Check if ps remoting is active"


$hostname = Invoke-Command -ComputerName 127.0.0.1 -ScriptBlock { hostname }

Write-Output "PS INFO: Hostname is $hostname"

$result = @{
    PsErrorCode = 0
    Hostname = $hostname
}

$result | ConvertTo-Json -Depth 10

我想我必须将 runAs 选项以及用户和密码添加到 cmd,但到目前为止我还没有管理它。

也许有人知道如何以管理员身份启动脚本。

java powershell powershell-remoting
1个回答
0
投票

我找到了适合我的解决方案。

我的java应用程序在用户A下运行,该用户没有管理员权限。我从 java 启动一个新的 power shell 进程。我使用 -Credentials 参数以具有管理员权限的用户 B 身份运行 power shell 脚本。

在 power shell 脚本中,我首先检查脚本是否以提升的权限执行。因为从来没有出现过这种情况,所以我以提升的权限重新启动脚本(-Verb“runas”)。然后该脚本在具有提升权限的用户 B 下运行。

这些是我的问题以及我如何解决它们。如果有人知道更好的解决方案,请告诉我。

无法以提升的权限从 java(在用户 A 下运行)启动 powershell 脚本 -> 以普通权限但以用户 B 的身份启动 power shell,然后以提升的权限重新启动脚本。

无法从具有提升权限的 powershell 脚本向其调用者(具有非提升权限的 power shell 脚本)返回值。标准输出不可用 -> 我使用日志文件来获取返回值。

只有当用户接受 UAC concent 提示时,才能以提升的权限启动 Power shell 脚本。绕过 UAC concent 提示是不可能的。 -> 我接受这一点。到目前为止我还没有找到解决这个问题的方法。更改通知级别对我来说是没有选择的。

# This example can be used to execute powershell commands with elevated privileges
param (
    [string]$logFile, # The logfile is used for logging and returning to the calling process
    [string]$ip
)

# Get the current user
$currentActiveUser = whoami
# Get the complete path to this power shell file
$currentScriptPath = $MyInvocation.MyCommand.Definition

# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)

# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator


# Check to see if we are currently running "as Administrator" = elevated privileges
if ($myWindowsPrincipal.IsInRole($adminRole)) {
  Write-Output "PS INFO: Script $currentScriptPath is called by $currentActiveUser in elevated mode" >> $logFile

  # This is a PS remoting command to the the hostname of a remote pc
  # TODO: Add here the credentials of the remote pc
  $hostname = Invoke-Command -ComputerName $ip -ScriptBlock { hostname }
  $hostname = $hostname | Out-String  # Convert object to string
  $hostname = $hostname.Trim()        # Remove \r\n

  Write-Output "PS INFO: Hostname is $hostname" >> $logFile

  # Create a result hash table
  $result = @{
    PsErrorCode = 0
    Hostname = $hostname
  }

  # Write the result to the log file
  $result | ConvertTo-Json -Depth 10 | Out-File -FilePath $logFile -Append
  exit
  }
else
  {
  # This is the entry point because the initial time the script is executed with non elevated privileges
  Write-Output "PS INFO: Script $currentScriptPath is called by $currentActiveUser not in elevated mode" >> $logFile

  # Create a new process object that starts PowerShell
  $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";

  # Specify the current script path and name as a parameter
  $newProcess.Arguments = "$($myInvocation.MyCommand.Definition) -logFile '$logFile' -ip '$ip'"

  # Indicate that the process should be elevated
  $newProcess.Verb = "runas";

  # Start the process and wait for it to finish
  Start-Process -FilePath $newProcess.FileName -ArgumentList $newProcess.Arguments -Verb $newProcess.Verb -PassThru -Wait

  Write-Output "PS INFO: Exit non elevated mode" >> $logFile
  # Exit from the current, unelevated, process
  exit
  }
© www.soinside.com 2019 - 2024. All rights reserved.