Dynamic basic auth based on response status and comments translations

- the method  requires an additional parameter if the dynamic basic auth should be supported and the user gets a prompt to enter the credentials
snapshot
Jonas Letzbor 2022-04-10 16:00:03 +02:00
parent f54ea5bdd6
commit cf4a97ac2c
5 changed files with 90 additions and 44 deletions

View File

@ -62,6 +62,7 @@ public class InstallConfig {
protected String urlEnding = ""; protected String urlEnding = "";
protected char[] authUsername = null; protected char[] authUsername = null;
protected char[] authPassword = null; protected char[] authPassword = null;
protected boolean allowAskForBasicAuth = false;
private boolean createDesktopEntry = false; private boolean createDesktopEntry = false;
private String desktopWindowsICO = ""; private String desktopWindowsICO = "";
@ -184,11 +185,14 @@ public class InstallConfig {
* @param url the URL * @param url the URL
* @param basicAuthUser [ the user for the basic auth ] * @param basicAuthUser [ the user for the basic auth ]
* @param basicAuthPassword [ the passwort for the basic auth ] * @param basicAuthPassword [ the passwort for the basic auth ]
* @param askForBasicAuth when no basic auth credentials are given and the request gets a 401 response ask the user for credentials at the command line
*/ */
public void setDownloadURLForProgramm(String url, char[] basicAuthUser, char[] basicAuthPassword) { public void setDownloadURLForProgramm(String url, char[] basicAuthUser, char[] basicAuthPassword, boolean askForBasicAuth) {
this.downloadURL = url; this.downloadURL = url;
this.authUsername = basicAuthUser; this.authUsername = basicAuthUser;
this.authPassword = basicAuthPassword; this.authPassword = basicAuthPassword;
this.allowAskForBasicAuth = askForBasicAuth;
offline = false; offline = false;
} }
@ -199,14 +203,16 @@ public class InstallConfig {
* @param url die URL (without file extension) * @param url die URL (without file extension)
* @param basicAuthUser [ the user for the basic auth ] * @param basicAuthUser [ the user for the basic auth ]
* @param basicAuthPassword [ the passwort for the basic auth ] * @param basicAuthPassword [ the passwort for the basic auth ]
* @param askForBasicAuth when no basic auth credentials are given and the request gets a 401 response ask the user for credentials at the command line
* @param end die file ending of the file (.jar) * @param end die file ending of the file (.jar)
*/ */
public void setDownloadURLForProgramm(String url, char[] basicAuthUser, char[] basicAuthPassword, String end) { public void setDownloadURLForProgramm(String url, char[] basicAuthUser, char[] basicAuthPassword, boolean askForBasicAuth, String end) {
this.downloadURL = url; this.downloadURL = url;
this.authUsername = basicAuthUser; this.authUsername = basicAuthUser;
this.authPassword = basicAuthPassword; this.authPassword = basicAuthPassword;
this.urlEnding = end; this.urlEnding = end;
this.addVersion = true; this.addVersion = true;
this.allowAskForBasicAuth = askForBasicAuth;
offline = false; offline = false;
} }

View File

@ -14,7 +14,6 @@ import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Base64; import java.util.Base64;
import java.util.List; import java.util.List;
@ -94,7 +93,7 @@ public class Installer {
if (conf.getIsUser() && InstallConfig.getOsType() != OSType.WINDOWS) { System.out.println("userInstallation_notAvailable"); error = -10; } if (conf.getIsUser() && InstallConfig.getOsType() != OSType.WINDOWS) { System.out.println("userInstallation_notAvailable"); error = -10; }
System.out.println("\n" + Tr.get("installation_start", conf.getApplicationNameShort(), conf.getVersion()) + "\n"); System.out.println(Tr.get("installation_start", conf.getApplicationNameShort(), conf.getVersion()) + "\n");
// all running instances will be killed // all running instances will be killed
this.killRunningInstances(); this.killRunningInstances();
@ -114,7 +113,7 @@ public class Installer {
if (!conf.getOffline()) { if (!conf.getOffline()) {
System.out.print(Tr.get("installation_download") + ": "); System.out.print(Tr.get("installation_download") + ": ");
jarFile = this.downloadFile(conf.downloadURL, conf.addVersion, conf.urlEnding); jarFile = this.downloadFile(conf.downloadURL, conf.addVersion, conf.urlEnding, conf.getQuiet() ? false : conf.allowAskForBasicAuth);
if (error < 0) return; if (error < 0) return;
System.out.println("\r" + Tr.get("installation_download_success") + " "); System.out.println("\r" + Tr.get("installation_download_success") + " ");
} else { } else {
@ -906,14 +905,16 @@ public class Installer {
} }
/** /**
* Downloads a file from an Webserver (with bsic auth support -> set in config) * Downloads a file from an Webserver (with basic auth support -> set in config)
* *
* @param url URL * @param url URL
* @param addVersion if the architecture and bs should be added to the given URL -> windows_x64 | linux_arm32 * @param addVersion if the architecture and BS should be added to the given URL -> windows_x64 | linux_arm32
* @param end the file ending (the URL will be set without an file ending) * @param end the file ending (the URL will be set without an file ending)
* @param ascForBasicAuth when no basic auth credentials are given and the request gets a 401 response ask the user for credentials at the command line
*
* @return the path of the downloaded file (when an error occurred: null + logger.error) * @return the path of the downloaded file (when an error occurred: null + logger.error)
*/ */
private String downloadFile (String url2, boolean addVersion, String end) { private String downloadFile (String url2, boolean addVersion, String end, boolean askForAuth) {
String serverURL = conf.downloadURL; String serverURL = conf.downloadURL;
@ -922,24 +923,54 @@ public class Installer {
try { try {
URL url = new URL(serverURL); URL url = new URL(serverURL);
HttpURLConnection con = (HttpURLConnection) url.openConnection(); HttpURLConnection con = (HttpURLConnection) url.openConnection();
if (conf.authUsername != null && conf.authPassword != null) {
// check if basic auth is required
if (con.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
if (conf.authUsername == null || conf.authPassword == null) {
if (!askForAuth) { logger.log("e", "Baisc authentication required for downloading the file \"" + serverURL + "\"", ""); System.exit(-1); }
char[] username = conf.authUsername;
char[] password = conf.authPassword;
System.out.println("\n" + Tr.get("basicAuthRequired"));
if (System.console() == null) { System.out.println(Tr.get("noConsole")); System.exit(-1); }
if (username == null) {
System.out.print(Tr.get("username") + ": ");
username = System.console().readLine().strip().toCharArray();
}
if (password == null) {
System.out.print(Tr.get("password") + ": ");
password = System.console().readPassword();
}
System.out.println();
conf.authUsername = username;
conf.authPassword = password;
}
// add Basic-Auth
String auth = new String(conf.authUsername) + ":" + new String(conf.authPassword); String auth = new String(conf.authUsername) + ":" + new String(conf.authPassword);
byte[] authEncBytes = Base64.getEncoder().encode(auth.getBytes()); byte[] authEncBytes = Base64.getEncoder().encode(auth.getBytes());
String authHeaderValue = "Basic " + new String(authEncBytes); String authHeaderValue = "Basic " + new String(authEncBytes);
con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Authorization", authHeaderValue); con.setRequestProperty("Authorization", authHeaderValue);
con.setRequestProperty("X-Requested-With", "XMLHttpRequest"); con.setRequestProperty("X-Requested-With", "XMLHttpRequest");
} }
if (con.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
logger.log("e", "Authentication failed for url \"" + serverURL + "\"", "");
System.exit(-1);
}
try { try {
File download = File.createTempFile("Download-Installation", ".jar"); File download = File.createTempFile("Download-Installation", ".jar");
// für eine Statusanzeige wird zunächst die Dateigröße der Datei ermittelt (wird in Bytes ausgegeben) // for a download status the size of the downloadable file is determined (in Bytes)
double lenght = con.getContentLength(); double lenght = con.getContentLength();
if (lenght < 100 * 1024) { throw new Exception ("Probably not a file (lenght to short)"); } if (lenght < 100 * 1024) { throw new Exception ("Probably not a file (lenght to short)"); }
// diese wird nun in Megabyte angegeben, sowie auf 2 Stellen nach dem Komma (Es wird die bereits heruntergeladene Dateigröße im "Binärformat" angegeben // round to megabytes and two decimal points
lenght = Math.round(lenght / 1048576 * 100) / 100.0; lenght = Math.round(lenght / 1048576 * 100) / 100.0;
// es muss nun parallel die bereits heruntergeladene Dateigröße ermittelt werden // in parallel the already downloaded file size has to be determined
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
double lenghtTmp = lenght; double lenghtTmp = lenght;
Future<?> future = scheduler.scheduleWithFixedDelay(() -> { Future<?> future = scheduler.scheduleWithFixedDelay(() -> {

View File

@ -12,8 +12,9 @@ public class RunInConsole {
/** /**
* Öffnet das Programm in der Konsole, falls dieses noch nicht in solch einer ausgeführt wird * Opens the program inside a console if not already run inside a console window
* @param keepOpen Ob die Konsole nach dem Durchlauf des Programms geschlossen werden soll *
* @param keepOpen the console will stay opened after the program was closed
*/ */
public static void start(boolean keepOpen) { public static void start(boolean keepOpen) {
start (keepOpen, null, false, false); start (keepOpen, null, false, false);
@ -21,20 +22,22 @@ public class RunInConsole {
/** /**
* Öffnet das Programm in der Konsole, falls dieses noch nicht in solch einer ausgeführt wird * Opens the program inside a console if not already run inside a console window
* @param args Mit welchen Parametern die Main-Methode beliefert werden soll *
* @param keepOpen Ob die Konsole nach dem durchlauf des Programms geöffnet bleiben soll * @param args the command line options for the main method when calling the program inside the console again
* @param keepOpen the console will stay opened after the program finishes
*/ */
public static void start(String[] args, boolean keepOpen) { public static void start(String[] args, boolean keepOpen) {
start(keepOpen, args, false, false); start(keepOpen, args, false, false);
} }
/** /**
* Öffnet das Programm in der Konsole * Opens the program inside a console if not already run inside a console window
* @param args Mit welchen Parametern die Main-Methode beliefert werden soll *
* @param keepOpen Ob die Konsole nach dem durchlauf des Programms geöffnet bleiben soll * @param args the command line options for the main method when calling the program inside the console again
* @param forceRestart Ob ein Neustart gemacht werden soll, wenn das Programm bereits in der Konsole läuft * @param keepOpen the console will stay opened after the program finishes
* @param asAdmin Ob das Programm mit Administratorprivelegien gestartet werden soll (Powershell muss installiert sein) * @param forceRestart even restart the program when already running inside a console
* @param asAdmin start the console with administrator privileges (on Windows Powershell is required)
*/ */
public static void start(String[] args, boolean keepOpen, boolean forceRestart, boolean asAdmin) { public static void start(String[] args, boolean keepOpen, boolean forceRestart, boolean asAdmin) {
start(keepOpen, args, forceRestart, asAdmin); start(keepOpen, args, forceRestart, asAdmin);
@ -45,9 +48,9 @@ public class RunInConsole {
String executableName = getExecutableName(); String executableName = getExecutableName();
// wird vermutlich in einer IDE ausgeführt // probably executed inside IDE
if (executableName == null) return; if (executableName == null) return;
// wird bereits in der Konsole ausgeführt // is already executed in console
if (System.console() != null && !forceRestart) return; if (System.console() != null && !forceRestart) return;
startExecutableInConsole(executableName, keepOpen, asAdmin, args); startExecutableInConsole(executableName, keepOpen, asAdmin, args);
@ -57,17 +60,17 @@ public class RunInConsole {
/** /**
* Öffnen ein Konsolenfenster und startet in diesem die Jar-Datei * Opens the console windows and starts the jar file
* *
* @param executableName Der Name der Jar-Datei (ohne Pfad -> relativ) * @param executableName the name of the jar file (without the path -> relativ)
* @param stayOpenAfterEnd Ob das Konsolenfenster nach dem vollständigen durchlauf der Jar-Datei geschlossen werden soll * @param stayOpenAfterEnd keep the console windows opened after the run of the jar file
* @param asAdmin Ob das Programm mit Administratorprivelegien gestartet werden soll (Powershell muss installiert sein) * @param asAdmin start the console with administrator privileges (on Windows Powershell is required)
*/ */
private static void startExecutableInConsole(String executableName, final boolean keepOpen, final boolean asAdmin, String[] args) { private static void startExecutableInConsole(String executableName, final boolean keepOpen, final boolean asAdmin, String[] args) {
String command = null; String command = null;
// es müssen nun noch die Parameter ermittelt werden // determine the parameters
String strArgs = ""; String strArgs = "";
for (String currentArg: args) { for (String currentArg: args) {
strArgs += "\"" + currentArg + "\" "; strArgs += "\"" + currentArg + "\" ";
@ -107,14 +110,12 @@ public class RunInConsole {
if (output != null && !output.equals("")) { terminal = currentTerminal[0]; terminalCommand = currentTerminal[1]; break; } if (output != null && !output.equals("")) { terminal = currentTerminal[0]; terminalCommand = currentTerminal[1]; break; }
} }
if (terminal == null) break; if (terminal == null) break;
if (!asAdmin) { if (!asAdmin) {
if (keepOpen) new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "; exec bash'").start(); if (keepOpen) new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "; exec bash'").start();
else new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "'").start(); else new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "'").start();
} else { } else {
if (keepOpen) new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " sudo /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "; exec bash'").start(); if (keepOpen) new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " sudo /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "; exec bash'").start();
else new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " sudo /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "'").start(); else new ProcessBuilder("bash", "-c", terminal + " " + terminalCommand + " sudo /bin/sh -c 'java -jar \"" + executableName + "\" " + strArgs + "'").start();
} }
@ -133,7 +134,7 @@ public class RunInConsole {
/** /**
* @return Der Name der Jar-Datei <i> (BeMa_installer.jar) </i> * @return the name of the jar file <i> (MyInstaller.jar) </i>
*/ */
public static String getExecutableName() { public static String getExecutableName() {
@ -141,11 +142,11 @@ public class RunInConsole {
final CodeSource codeSource = RunInConsole.class.getProtectionDomain().getCodeSource(); final CodeSource codeSource = RunInConsole.class.getProtectionDomain().getCodeSource();
if (codeSource == null) { if (codeSource == null) {
// es wird nichts geloggt // do nothing
} else { } else {
String path = codeSource.getLocation().getPath(); String path = codeSource.getLocation().getPath();
if (path == null || path.isEmpty()) { if (path == null || path.isEmpty()) {
// es wird nichts geloggt; // do nothing
} else { } else {
executableNameFromClass = new File(path).getName(); executableNameFromClass = new File(path).getName();
} }
@ -165,18 +166,18 @@ public class RunInConsole {
/** /**
* Gibt zurück, ob es sich um eine .jar Datei handelt, und ob diese existiert * Checks if the given file path is valid and if its a jar file
* @param name Name der Jar Datei *
* @return Ob es sich um eine Jar-Datei handelt * @param the name of the jar file
* @return the file path is valid and a jar file
*/ */
private static boolean isJarFile(final String name) { private static boolean isJarFile(final String name) {
if (name == null || !name.toLowerCase().endsWith(".jar")) return false; if (name == null || !name.toLowerCase().endsWith(".jar")) return false;
// überprüfe, ob diese existiert // checks if file exists
final File file = new File(name); final File file = new File(name);
return file.exists() && file.isFile(); return file.exists() && file.isFile();
} }
} }

View File

@ -31,3 +31,7 @@ created=erstellt
failed=fehlgeschlagen failed=fehlgeschlagen
errorMessage=Fehlermeldung errorMessage=Fehlermeldung
successful=erfolgreich successful=erfolgreich
basicAuthRequired=Zum herunterladen des Programms ist eine Authentifizierung erforderlich (HTTP-Code 401)
username=Benutzername
password=Passwort

View File

@ -31,3 +31,7 @@ created=created
failed=failed failed=failed
errorMessage=Error Message errorMessage=Error Message
successful=successful successful=successful
basicAuthRequired=For downloading the program a authentication is required (HTTP-Code 401)
username=Username
password=Password