better error handling on failed logins

This commit is contained in:
Peter Hormanns 2016-08-31 16:53:03 +02:00
parent e34843c21d
commit 664136d563
8 changed files with 131 additions and 63 deletions

View File

@ -7,6 +7,7 @@ import java.io.InputStreamReader;
import de.hsadmin.jscli.conf.CommandlineParser; import de.hsadmin.jscli.conf.CommandlineParser;
import de.hsadmin.jscli.console.ConsoleWrapper; import de.hsadmin.jscli.console.ConsoleWrapper;
import de.hsadmin.jscli.exception.JSCliException;
import de.hsadmin.jscli.json.JSONFormatter; import de.hsadmin.jscli.json.JSONFormatter;
@ -65,8 +66,8 @@ public class Main {
try { try {
scriptClient.execute(command); scriptClient.execute(command);
console.println(formatter.format(scriptClient.getLastRpcResult())); console.println(formatter.format(scriptClient.getLastRpcResult()));
} catch (Exception e) { } catch (JSCliException e) {
console.println("Error: " + e.getLocalizedMessage() + "\n"); console.println(findRootException(e) + "\n");
} }
command = console.readInput(); command = console.readInput();
} }
@ -77,4 +78,12 @@ public class Main {
} }
} }
private static String findRootException(final Exception exp) {
Throwable cause = exp;
while (cause.getCause() != null && cause.getCause() != cause) {
cause = cause.getCause();
}
return "Error: " + cause.getLocalizedMessage();
}
} }

View File

@ -11,7 +11,6 @@ import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient; import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import de.hsadmin.jscli.cas.CASTicketProvider;
import de.hsadmin.jscli.conf.Config; import de.hsadmin.jscli.conf.Config;
import de.hsadmin.jscli.exception.JSCliException; import de.hsadmin.jscli.exception.JSCliException;
@ -22,7 +21,7 @@ public class RpcClient {
private final List<XmlRpcClient> clientList; private final List<XmlRpcClient> clientList;
private final Map<String, XmlRpcClient> clientMap; private final Map<String, XmlRpcClient> clientMap;
public RpcClient(final CASTicketProvider tgt) throws JSCliException { public RpcClient() throws JSCliException {
clientList = new ArrayList<XmlRpcClient>(); clientList = new ArrayList<XmlRpcClient>();
clientMap = new HashMap<String, XmlRpcClient>(); clientMap = new HashMap<String, XmlRpcClient>();
try { try {

View File

@ -11,7 +11,7 @@ import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager; import javax.script.ScriptEngineManager;
import javax.script.ScriptException; import javax.script.ScriptException;
import de.hsadmin.jscli.cas.CASTicketProvider; import de.hsadmin.jscli.cas.TicketProviderFactory;
import de.hsadmin.jscli.console.ConsoleWrapper; import de.hsadmin.jscli.console.ConsoleWrapper;
import de.hsadmin.jscli.exception.JSCliException; import de.hsadmin.jscli.exception.JSCliException;
@ -21,11 +21,9 @@ public class ScriptClient {
final private Set<String> completionStrings; final private Set<String> completionStrings;
public ScriptClient(final ConsoleWrapper console, final String user, final String runAs, final String... arguments) throws JSCliException { public ScriptClient(final ConsoleWrapper console, final String user, final String runAs, final String... arguments) throws JSCliException {
final CASTicketProvider ticketProvider = new CASTicketProvider(console, user, runAs); final RpcClient rpcClient = new RpcClient();
final RpcClient rpcClient = new RpcClient(ticketProvider); engine = new ScriptEngineManager().getEngineByName("js");
final ScriptEngineManager engineManager = new ScriptEngineManager(); engine.put("casgrantingticket", TicketProviderFactory.getInstance(console, user, runAs));
engine = engineManager.getEngineByName("js");
engine.put("casgrantingticket", ticketProvider);
engine.put("xmlrpcclient", rpcClient); engine.put("xmlrpcclient", rpcClient);
engine.put("xmlrpcLastResult", null); engine.put("xmlrpcLastResult", null);
completionStrings = new HashSet<String>(); completionStrings = new HashSet<String>();

View File

@ -0,0 +1,13 @@
package de.hsadmin.jscli;
import java.io.FileNotFoundException;
import de.hsadmin.jscli.exception.JSCliException;
public interface TicketProvider {
public String getTicket() throws JSCliException, FileNotFoundException;
public String getRunAs();
}

View File

@ -18,14 +18,12 @@ import java.util.Properties;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import de.hsadmin.jscli.TicketProvider;
import de.hsadmin.jscli.conf.Config; import de.hsadmin.jscli.conf.Config;
import de.hsadmin.jscli.console.PasswordReader; import de.hsadmin.jscli.console.PasswordReader;
import de.hsadmin.jscli.exception.JSCliException; import de.hsadmin.jscli.exception.JSCliException;
public class CASTicketProvider { public class CASTicketProvider implements TicketProvider {
private static final String LOGIN_URL = "https://login.hostsharing.net:443/cas/v1/tickets";
private static final String BACKEND_URL = "https://config.hostsharing.net:443/hsar/backend";
final private String loginURL; final private String loginURL;
final private String backendURL; final private String backendURL;
@ -35,13 +33,12 @@ public class CASTicketProvider {
private String grantingTicket; private String grantingTicket;
public CASTicketProvider(final PasswordReader console, final String user, final String runAs) throws JSCliException { public CASTicketProvider(final PasswordReader console, final String user, final String runAs, final String backendURL, final String loginURL) throws JSCliException {
this.passwordReader = console; this.passwordReader = console;
this.user = user; this.user = user;
this.runAs = runAs; this.runAs = runAs;
final Config config = Config.getInstance(); this.backendURL = backendURL;
backendURL = config.getProperty("backendURL", BACKEND_URL); this.loginURL = loginURL;
loginURL = config.getProperty("loginURL", LOGIN_URL);
if ("TestUmgebung".equals(loginURL)) { if ("TestUmgebung".equals(loginURL)) {
grantingTicket = "ticket:" + user; grantingTicket = "ticket:" + user;
} else { } else {
@ -49,19 +46,39 @@ public class CASTicketProvider {
} }
} }
@Override
public String getTicket() throws JSCliException, FileNotFoundException { public String getTicket() throws JSCliException, FileNotFoundException {
if (grantingTicket != null && grantingTicket.startsWith("ticket:")) {
return grantingTicket.replaceFirst("ticket", "user");
}
try { try {
String encodedParams = URLEncoder.encode("service", "UTF-8") final String encodedParams =
+ "=" + URLEncoder.encode(backendURL, "UTF-8"); URLEncoder.encode("service", "UTF-8") + "=" + URLEncoder.encode(backendURL, "UTF-8");
return doHttpPost(grantingTicket, encodedParams); String urlString = grantingTicket;
String result = null;
boolean grantingTicketIsValid = false;
int trails = 0;
while (!grantingTicketIsValid) {
try {
result = requestForServiceTicket(urlString, encodedParams);
grantingTicketIsValid = true;
grantingTicket = urlString;
saveProperties(grantingTicket, getTicketFile());
} catch (IOException e) {
if (trails > 0) {
passwordReader.println("login failed");
}
trails++;
if (trails > 3) {
throw new JSCliException("exceeded number of login attempts");
}
urlString = getGrantingTicket();
}
}
return result;
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new JSCliException(e); throw new JSCliException(e);
} }
} }
@Override
public String getRunAs() { public String getRunAs() {
return runAs; return runAs;
} }
@ -77,7 +94,7 @@ public class CASTicketProvider {
+ "=" + URLEncoder.encode(user, "UTF-8") + "=" + URLEncoder.encode(user, "UTF-8")
+ "&" + URLEncoder.encode("password", "UTF-8") + "&" + URLEncoder.encode("password", "UTF-8")
+ "=" + URLEncoder.encode(password, "UTF-8"); + "=" + URLEncoder.encode(password, "UTF-8");
grantingTicket = doHttpPost(loginURL, encodedParams); grantingTicket = requestForGrantingTicket(loginURL, encodedParams);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new JSCliException(e); throw new JSCliException(e);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
@ -90,47 +107,30 @@ public class CASTicketProvider {
return passwordReader.readPassword(); return passwordReader.readPassword();
} }
private String doHttpPost(final String urlString, final String encodedParams) throws JSCliException, FileNotFoundException { private String requestForGrantingTicket(final String urlString, final String encodedParams) throws JSCliException, FileNotFoundException {
String result = null;
try { try {
result = extractTicket(urlString, encodedParams); final HttpsURLConnection connection = doConnect(urlString, encodedParams);
} catch (FileNotFoundException e) { return connection.getHeaderField("Location");
grantingTicket = getGrantingTicket();
saveProperties(grantingTicket, getTicketFile());
try {
result = extractTicket(grantingTicket, encodedParams);
} catch (IOException e1) {
throw new JSCliException(e1);
}
} catch (IOException e) { } catch (IOException e) {
throw new JSCliException(e); throw new JSCliException(e);
} }
return result;
} }
private String extractTicket(final String urlString, private String requestForServiceTicket(final String urlString, final String encodedParams)
final String encodedParams) throws MalformedURLException, throws MalformedURLException, IOException, ProtocolException
IOException, ProtocolException { {
String result;
final HttpsURLConnection connection = doConnect(urlString, encodedParams); final HttpsURLConnection connection = doConnect(urlString, encodedParams);
final String ticket = readTicket(connection); final InputStreamReader inputStreamReader = new InputStreamReader(connection.getInputStream());
if (ticket != null && ticket.startsWith("ST-")) { final BufferedReader reader = new BufferedReader(inputStreamReader);
result = ticket;
} else {
result = connection.getHeaderField("Location");
}
return result;
}
private String readTicket(final HttpsURLConnection connection)
throws IOException {
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
final String ticket = reader.readLine(); final String ticket = reader.readLine();
String readLine = null; String readLine = null;
do { do {
readLine = reader.readLine(); readLine = reader.readLine();
} while (readLine != null); } while (readLine != null);
return ticket; if (ticket != null && ticket.startsWith("ST-")) {
return ticket;
}
return null;
} }
private HttpsURLConnection doConnect(final String urlString, private HttpsURLConnection doConnect(final String urlString,
@ -151,15 +151,9 @@ public class CASTicketProvider {
} }
private String readFiledGrantingTicket() throws JSCliException { private String readFiledGrantingTicket() throws JSCliException {
String filedTicket = null;
final File file = getTicketFile(); final File file = getTicketFile();
final Properties properties = loadProperties(file); final Properties properties = loadProperties(file);
filedTicket = properties.getProperty(user); return properties.getProperty(user);
if (filedTicket == null) {
filedTicket = getGrantingTicket();
saveProperties(filedTicket, file);
}
return filedTicket;
} }
private File getTicketFile() { private File getTicketFile() {
@ -173,7 +167,7 @@ public class CASTicketProvider {
if (filedTicket != null) { if (filedTicket != null) {
properties.setProperty(user, filedTicket); properties.setProperty(user, filedTicket);
try { try {
properties.store(new FileOutputStream(file), ""); properties.store(new FileOutputStream(file), "stored cas tickets");
} catch (IOException e) { } catch (IOException e) {
throw new JSCliException(e); throw new JSCliException(e);
} }

View File

@ -0,0 +1,28 @@
package de.hsadmin.jscli.cas;
import java.io.FileNotFoundException;
import de.hsadmin.jscli.TicketProvider;
import de.hsadmin.jscli.exception.JSCliException;
public class TestTicketProvider implements TicketProvider {
private final String grantingTicket;
private final String runAs;
public TestTicketProvider(final String user, final String runAs) {
this.grantingTicket = "user:" + user;
this.runAs = runAs;
}
@Override
public String getTicket() throws JSCliException, FileNotFoundException {
return grantingTicket;
}
@Override
public String getRunAs() {
return runAs;
}
}

View File

@ -0,0 +1,25 @@
package de.hsadmin.jscli.cas;
import de.hsadmin.jscli.TicketProvider;
import de.hsadmin.jscli.conf.Config;
import de.hsadmin.jscli.console.PasswordReader;
import de.hsadmin.jscli.exception.JSCliException;
public class TicketProviderFactory {
private static final String HOSTSHARING_LOGIN_URL = "https://login.hostsharing.net:443/cas/v1/tickets";
private static final String HOSTSHARING_BACKEND_URL = "https://config.hostsharing.net:443/hsar/backend";
public static TicketProvider getInstance(final PasswordReader console, final String user, final String runAs) throws JSCliException
{
final Config config = Config.getInstance();
final String backendURL = config.getProperty("backendURL", HOSTSHARING_BACKEND_URL);
final String loginURL = config.getProperty("loginURL", HOSTSHARING_LOGIN_URL);
if ("TestUmgebung".equalsIgnoreCase(loginURL)) {
return new TestTicketProvider(user, runAs);
} else {
return new CASTicketProvider(console, user, runAs, backendURL, loginURL);
}
}
}

View File

@ -4,6 +4,8 @@ import de.hsadmin.jscli.exception.JSCliException;
public interface PasswordReader { public interface PasswordReader {
String readPassword() throws JSCliException; public String readPassword() throws JSCliException;
public void println(final String text) throws JSCliException;
} }