Best practice: catching failure points in java.net.URL - java

New to the JVM, working with Scala and Play 2.0
I'm converting a legacy application over to Play, one that requires payment processing via Authorize.net. Looking through java.net.URL source, there are numerous potential points of failure. Given the interface I've written below, where would you implement try/catch blocks? I'll need to adapt method signatures accordingly, probably returning an Either[Error, Success] to calling client code
import java.net.{URL, URLEncoder}
import java.io.{BufferedReader, DataOutputStream, InputStreamReader}
import javax.net.ssl._
trait Authnet {
private val prodUrl = "https://secure.authorize.net/gateway/transact.dll"
private val testUrl = "https://test.authorize.net/gateway/transact.dll"
protected def authNetProcess(params: Map[String,String]) = {
val(conn, urlParams) = connect(params)
val request = new DataOutputStream( conn.getOutputStream )
request.write(urlParams.getBytes)
request.flush()
request.close()
val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
val results = response.readLine().split("\\|")
response.close()
results.toList
}
private def connect(params: Map[String,String]) = {
val urlParams = (config ++ params) map { case(k,v) =>
URLEncoder.encode(k, "UTF-8") + "=" + URLEncoder.encode(v, "UTF-8")
} mkString("&")
lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
val conn = url.openConnection
conn.setDoOutput(true)
conn.setUseCaches(false)
(conn, urlParams)
}
private val config = Map(
'x_login -> "...",
'x_tran_key -> "...",
...
)
}

Stick to the thumb rule:
Only catch an exception if you must handle it.
There is no sharp definition for "must handle" but it means you should resist the urge to catch an exception because you can just to throw a different exception.
The "must handle" is mainly defined by how your application should work or other dependencies.
If the application requires to display an error to the user instead of aborting with an exception, then it's a must.
In that case catching the excpetion adds also some meaningful processing.
If an API requires to throw a different exception, then it's a must, but the APIs definition is possibly not sound.
I am always questioning the added value of replacing an exception with just another exception.
Applying this to your example:
Would it add some value to catch an exception from connect() in authNetProcess()?
No! There is no way to handle that exception inside of connect(). So its ok to leave that exception to the caller of authNetProcess. There you could provide different handling based on the kind of the exception.

EDIT
Well, if any part of the connection/stream process fails, the transaction is hosed, so silly to only capture error on opening of the connection. I'm just wrapping the whole transaction in a catching (operation) option block, and leaving it at that; I'm not too concerned re: the exact cause of the error (whatever it is gets logged) as it is transient, so catch it, have the user try again; if error persists, contact us...
ORIGINAL
OK, well, given the up votes and lack of commentary to-date, the only conclusion I can draw is...nobody around here knows what they're doing! heh, heh, joking ;-)
Although I'm new to the JVM, try/catch/finally bloat is getting old fast; via the wonders of Scala type inference, I have abstracted away general error handling into concise implementations:
catching ( operation ) option
catching ( operation ) either
Unless I receive feedback otherwise, for now I'm copping out by just catching connection creation (I believe, in this case, the most likely error condition). Here's the new implementation:
protected def authNetProcess(params: Map[String,String]) = {
connect() match {
case Some(conn) =>
val request = new DataOutputStream(conn.getOutputStream)
request.write(getUrlParams(params).getBytes)
request.flush()
request.close()
val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
val results = response.readLine().split("\\|")
response.close()
results.toList
case None => List[String]()
}
}
private def connect() = {
lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
catching ( url.openConnection ) option match {
case Some(conn) =>
conn.setDoOutput(true)
conn.setUseCaches(false)
//conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
Some(conn)
case None => None // connection failed
}
}
I suppose a more rigorous approach would be to extract all potential error conditions into maybeWorked Option operations, and then wrap them all up in a for comprehension. That's probably the proper/responsible approach...but only so many hours in a day, will revisit this later
feedback appreciated!

Related

ChromeDevTools in selenium, waiting for response bodies

I need to work on ajax response, that is one of responses received upon visiting a page. I use selenium dev tools and java. I create a listener, that intercepts a specific request and then I want to work on response it brings. However I need to setup static wait, or else selenium don't have time to save RequestId. I read Chrome Dev Tools documentation, but it's a new thing for me. I wonder if there is a method that would allow me to wait for this call to be completed, other than the static wait.
Here is my code:
#Test(groups = "test")
public void x() throws InterruptedException, JsonProcessingException {
User user = User.builder();
ManageAccountStep manageAccountStep = new ManageAccountStep(getDriver());
DashboardPO dashboardPO = new DashboardPO(getDriver());
manageAccountStep.login(user);
DevTools devTools = ((HasDevTools) getDriver()).maybeGetDevTools().orElseThrow();
devTools.createSessionIfThereIsNotOne();
devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));
// end of boilerplate
final RequestId[] id = new RequestId[1];
devTools.addListener(Network.responseReceived(), response -> {
log.info(response.getResponse().getUrl());
if (response.getResponse().getUrl().contains(DESIRED_URL)){
id[0] = response.getRequestId();
}
});
dashboardPO
.clickLink(); // here is when my DESIRED_URL happens
Utils.sleep(5000); // Something like Thread.sleep(5000)
String responseBody = devTools.send(Network.getResponseBody(id[0])).getBody();
// some operations on responseBody
devTools.clearListeners();
devTools.disconnectSession();
}
If I don't use 5 seconds wait id variable gets never assigned and I null pointer exception requestId is required. During these 5 seconds log.info prints all api calls that are happening and it almost always finds my id. I would like to refrain from static wait though. I am thinking about something similiar to maybe jQuery.active()==0, but my page doesn't use jQuery.
You may try custom function Explicit Wait. Something like this:
public String getResponseBody(WebDriver driver, DevTools devTools) {
return new WebDriverWait(driver,5)
.ignoring(NullPointerException.class)
.until(driver ->
devTools.send(Network.getResponseBody(id[0])).getBody());
}
So, it won't wait for all 5 seconds. The moment it got the data, it would come of out of the until method. Also add whichever Exception that was coming up here.
Has put these lines of code as separate method because, devTools object is locally defined. In order to use them inside this anonymous inner function, it has to be final or effectively final.
I seem to run into this issue when running tests in parallel (and headless) and trying to capture the requests and responses, I get:
{"No data found for resource with given identifier"},"sessionId" ...
However, now .until seems to only take ExpectedCondition
So a similar solution (to the accepted answer), but without using "WebDriverWait.until" that I use is:
public static String getResponseBody(DevTools devTools, RequestId id) {
String requestPostData = "";
LocalDateTime then = LocalDateTime.now();
String err = "";
Integer it = 0;
while (true) {
err = "";
try{requestPostData = devTools.send(Network.getResponseBody(id)).getBody();} catch( Exception e){err = e.getMessage();};
if (requestPostData != null && !requestPostData.equals("")) {break;}
if (err.equals("")) {break;} // if we don't have an error message, its quite possible the responseBody really is an empty string
long timeTaken = ChronoUnit.SECONDS.between(then, LocalDateTime.now());
if (timeTaken >= 5) {requestPostData = err + ", timeTaken:" + timeTaken; break;}
if(it > 0) {TimeUnit.SECONDS.sleep(it);} // I prefer waiting longer and longer, avoiding stack overflows
it++;
}
return requestPostData;
}
It just loops until it doesn't error, and returns the string back as soon as it can (but I actually set timeTaken >= 60 due to many parallel requests)

Checkmarx SQL injection high severity issue

I am getting a high severity issue in this method:
public void recordBadLogin(final String uid, final String reason, final String ip) throws DataAccessException {
if (Utils.isEmpty(uid)) {
throw new DataAccessException("User information needed to update , Empty user information passed");
}
try {
String sql = (String) this.queries.get(IUtilDAO.queryKeyPrefix + UtilDAO.RECORD_FAILED_LOGIN);
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("uid", uid.trim());
paramMap.put("reason", (reason != null ? reason.trim() : "Invalid userid/password"));
paramMap.put("ip", ip);
this.namedJdbcTemplate.update(sql, paramMap);
} catch (Exception e) {
throw new DataAccessException("Failed to record bad login for user " + uid, e);
}
}
This line of code is causing the issue:
String sql = (String) this.queries.get(IUtilDAO.queryKeyPrefix + UtilDAO.RECORD_FAILED_LOGIN);
queries is a properties object and the prepared statement is being retrieved given IUtilDAO.queryKeyPrefix + UtilDAO.RECORD_FAILED_LOGIN. And those 2 arguments are constants. Logically I don't see how this can cause an SQL injection issue as the prepared statement is being retrieved from a dictionary. Does anyone have an idea if this is a false positive or if there is an actual vulnerability present?
It's hard to tell from the example given, but I'd guess that the properties object was tainted by untrusted data. Most code flow analysis tools will taint the entire data structure if any untrusted data is placed in it.
Technically this is a "false positive". But architecturally it's something that should be fixed - it's generally a bad idea to mix trusted and untrusted data together in the same data structure. It makes it easy for future developers to misunderstand the status of a particular element, and makes it harder for both humans and tools to code review for security issues.

webMethods getting the root cause for a ServiceException

I get the following exception when calling the http service:
com.wm.app.b2b.server.ServiceException
Message: com.wm.net.NetException: [ISC.0064.9314] Authorization Required: Unauthorized
So far, so good. But I would like to get that information programatically - not the human readable translation.
I seem to have no chance to get the status code 401 or something that is a 100% proof that the problem is a 401.
Writing a wrapper that tries to get the "root cause" (getCause...) does not work. There is no other "cause"...
All I have are parsable strings. Any idea?
UPDATE
I found a way to get it done - using a deprecated method...:
...
try {
output =
Service.doInvoke( "my.package.authentication", "checkAuthentication", input );
} catch( final ServiceException sEx ) {
// if this is deprecated: how to we have to handle this in future?
final Throwable wrappedEx = sEx.getWrappedException();
// return early
if(null == wrappedEx || !NetException.class.isInstance(wrappedEx) ) {
throw sEx;
}
// process the net exception
final NetException nEx = (NetException)wrappedEx;
final String responseBody = convertStreamToString(nEx.getResponseInputStream());
// process the returned body wrapped by the net exception
final Gson gson = new Gson();
final ErrorData errorData = gson.fromJson(responseBody, ErrorData.class);
// check if the problem is an invalid token
tokenIsInvalid = errorData.code.equals(INVALID_TOKEN_EXCEPTION__CODE_STRING);
} catch( Exception e ) {
// wrap the exception in a service exception and throw it
throw new ServiceException(e);
}
...
A better solution would simply check the HTTP-Status-Code - but a 401 is gone forever if recieved by the http-service... :-|
Hi usually that kind of error is due to the Execution ACL that is wrongly set on your web service (assuming that your http service is actually a SOAP web service).
With webMethods Designer 9.2,
Open your web service descriptor
In the properties, click on "Permissions"
Set "Execution ACL" to "Anynomous"
If what you're exposing is actually a REST web service then the process is pretty much the same. The "Permission" property will be in your flow service's properties.
Hope this helps

Java - LDAP: Attribute is Read-Only

I am using UnboundID-LDAPSDK (2.3.8) to change the user's photo in our Microsoft Active Directory.
LDAPConnection ldap = null;
try {
ldap = new LDAPConnection("domain-srv", 389, "CN=admin,OU=Users,OU=ADM,DC=domain,DC=local", "password");
SearchResult sr = ldap.search("DC=domain,DC=local", SearchScope.SUB, "(sAMAccountName=" + getUser().getUsername() + ")");
if (sr.getEntryCount() == 1) {
SearchResultEntry entry = sr.getSearchEntries().get(0);
entry.setAttribute("thumbnailPhoto", getUser().getPhotoAsByteArray());
ldap.close();
return true;
} else
return false;
} catch (LDAPException e) {
e.printStackTrace();
}
But I get a java.lang.UnsupportedOperationException.
The documentation for setAttribute states:
Throws an UnsupportedOperationException to indicate that this is a
read-only entry.
I also tried to change the postalCode but I get the same exception.
Changing those attributes should be possible, because I can change them with jXplorer.
Do I have to enable a write-mode somehow?
Thank you
The SearchResultEntry object extends ReadOnlyEntry and is therefore immutable. But even if it weren't, merely calling entry.setAttribute would have no effect on the data in the server. You have to use a modify operation for that.
To do that, you'd need something like:
ModifyRequest modifyRequest = new ModifyRequest(entry.getDN(),
new Modification(ModificationType.REPLACE,
"thumbnailPhoto", getUser().getPhotoAsByteArray());
ldap.modify(modifyRequest);
Also, you should put the call to ldap.close() in a finally block because as the code is written now, you're only closing the connection if the search is successful and returns exactly one entry, but not if the search fails, doesn't match any entries, or the attempt to perform the modify fails.

Why would this cause a StringIndexOutOfBoundsException? Android

I am working on a small file manager to help me learn the basics of android, but I keep running into an error. WHenever I have a lot of items in the folder, it crashes and I get a message similar to this one,
java.lang.StringIndexOutOfBoundsException: length=26; regionStart=23; regionLength=-2
What could be causing this? The line it points to is line 2:
1.)String mimeType = "";
2.)mimeType = URLConnection.guessContentTypeFromName(f.getName());
You are missing some key lines we need to see, such as where f (a File? a URI?) is defined. However when I have seen this problem before it was caused by a URI with no Protocol set.
Making sure you have an extension and using MimeTypeMap#getMimeTypeFromExtension() is probably a good bet too
This error happens to me when the URL has a fragment, which can be identified by a # followed by some value. (For more on URL fragments, see https://www.w3.org/Addressing/URL/4_2_Fragments.html)
The URL fragment is not helpful in guessing content type, and since it is problematic in this case, it should be removed before calling URLConnection.guessContentTypeFromName().
Here is a simple function that returns a URL without the fragment:
private fun getSafeUrlForGuessing(url: String): String {
return try {
val uri = Uri.parse(url)
if (uri.scheme?.startsWith("http") == true) {
uri.buildUpon()
.fragment(null) // URLs with fragments cause URLConnection.guessContentTypeFromName() to throw
.build()
.toString()
} else {
url
}
} catch (error: Throwable) {
url
}
}

Categories