Play Framework double url encoding - java

given the following controller method where username = bob and emailAddress = bob#bob.com
public static void resetPassword(String username, String emailAddress) {
String url = BASE_URL + "/users/" + username + "/reset_password";
HttpResponse response = WS.url(url).setParameter("email_address", emailAddress).get();
}
Sometimes when I make the call the url endpoing receives:
localhost:8080/api/v1/users/bob/reset_password?email_address=bob%40bob.com
then other times i get:
localhost:8080/api/v1/users/bob/reset_password?email_address=bob%2540bob.com
On the second one the # has been encoded once to %40 then the % was again encoded to %25 so you end up with %2540
If I do nothing more than wait a minute the problem goes away which makes me think it's some sort of caching problem but I can't seem to figure out what it is.

finally been recognized as a bug and has been fixed in a later release

since this does not repeduce all the times i dont know if that will help but did you try to encode the url? for example :
org.apache.commons.httpclient.util.URIUtil.encodeAll(url);

I think what is happening is when you are calling the controller the first time you send the at symbol as an at symbol.
This then gets encoded into the response and the # is converted to %40. I'm guessing when you get this back and you resend it through the browser the % in the %40 gets encoded to %25 making it %2540.
Sorry if the above is confusing, it is difficult to explain.
Simple answer would be to just do a replace on the emailAddress variable of %40 to # before passing it into WS class. There is also a urlDecode() method in the play framework which may do the trick, I've used play before but I haven't used this method.

I suspect some form of URL rewriting. Do you have an Apache Web Server running in front of your server? Maybe some RewriteRule is missing the [NE] flag.

Related

How to test a HTTP request

I have set up this simple http request, which simply returns a "hello world" response to my IDE terminal. I have been looking into testing and I am not quite sure how i would test what this method is returning.
Currently i have done my own research into JUnit, but again i am not even sure if this would be the correct tool to use for this problem. I only researched this as it is a Java tool.
public static void newRequest() throws IOException {
URL helloServer = new URL("http://localhost:5050/");
HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory();
HttpRequest request = requestFactory.buildGetRequest(new GenericUrl(helloServer));
HttpResponse rawResponse = request.execute();
String responseString = rawResponse.parseAsString();
logger.debug(responseString);
}
Any guidance on this would be greatly appreciated.
Does the function even need to be tested?
Does the function even need to be tested? Well, that is entirely up to you. Does this function contain code that is critical to your application? If so then yes. If the impact of a bug in this function is minimal then probably not.
Assuming that you want to test this, then:
The method in question is not returning anything void before the function name says this. You will need to look at testing the logic of the function. In this case you need to check that the correct response is received. There are two ways that I can think of to do this:
Modify the code to return the response.
You could change the function to return a String and then return rawResponse.parseAsString(); (which is the same thing you are logging.
Then you can call the function from the test and check the String that is returned.
Get the log message from your logger.
Depending on the logging that you are using, you could get the log message that was written by the function. Assuming log4j then there are some posts on how to do this:
log4j: how to get the last inserted log message?
Personally, I prefer the first option as it is less effort. I would also consider returning the body of the response rather than the raw response.

Not getting request parameter value thru chrome/firefox. Related to double escaping?

Here is my link
"customer.action?custId=211&custAddressId=2341";
This url string is the output of c:out tag in jsp.
In Firefox/Chrome I am getting the value of custAddressId as null. Reason I think(almost sure) is happening because Chrome/Firefox
are escaping the already ecsaped value(thats why I am getting the second paramter name as amp;custAddressId instead of custAddressId)
but IE does not do that.
Is there a way i can configure my tomcat 6 to get the right paramters(even if it is double escaped).
If not is there a way i can handle it in c:out or browser level itself where i do not need to browser specific code ?
No. There is no way you can configure Tomcat to do double unescaping. You need to make sure your client is sending the correct data.

simple example of native app passing string to website?

Can somebody give a simple example for java code of a native app passing a string to a website?
For example: when a string has the value Hello everybody, the text Hello everybody should get pasted into the Google search field.
For the most simple use, you can try:
public static void browseURL(Activity activity, String url)
{
try
{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
activity.startActivity(intent);
}
catch (Exception e)
{
message(activity, "Sorry, failed to view the desired page.");
}
}
and then call:
browseURL("http://www.google.com/search?q=Hello+World")
Do you want to fill the fields and submit them? If so, just do the request with the request parameters filled, and parse the response given by the server. Look into Apache HttpClient.
You don't actually have to add text to the Google search field explicitly. You can send a URL with a query string.
Depending on the website the query string will always be different. For Google it is http://www.google.ca/search?q=something . Anything after a ? is considered a query string which any good web developer will include in a webpage. That query string takes custom commands in the form of ?command=query for command&command2=query for command 2.
Since this is tagged blackberry, I assume you want to implement a blackberry app, and you don't explicitly explain what you want to do, so you have two options,
Invoke the browser
On that page it describes how to open a browser session. So within the
browserSession.displayPage("http://http://www.google.ca/search?q=searching%20for%20something");
If you need a class for URL encoding, let me know and I'll send one your way.
Http Request to pull the html of the webpage into the code. To do that, you'll have to look at my blog this week as I'll be posting a full in code network class either tomorrow or tuesday, which I'll edit this post to contain a link to.
OR you can send me a message if you need it NOW and I can email the non-cleaned up code to you.

How do I resolve "WILL_NOT_PERFORM" MS AD reply when trying to change password in scala w/ the unboundid LDAP SDK?

I'm wrestling with Active Directory, trying to get it to let me change a password. I've found tons of useful information, but I'm still getting a persistent error.
Some code:
import com.unboundid.ldap.sdk._
import com.unboundid.util.ssl._
def main(args: Array[String]) : Unit = {
var sslUtil = new SSLUtil( new TrustAllTrustManager() )
var con = new LDAPConnection(sslUtil.createSSLSocketFactory())
con.connect("ldap.example.net", 636)
con.bind("ldapadmin", "adminpasswd")
val newPass = "Jfi8ZH8#k".getBytes("UTF-16LE");
val modRequest = new ModifyRequest("dn: cn=Tester Dude,ou=Lab,ou=Org,ou=Provider,DC=example,DC=net",
"changetype: modify",
"replace: unicodePwd",
"unicodePwd: " + '"' + newPass + '"')
println("\nGoing to try to set password to " + newPass + " with: " + modRequest.toString())
try {
con.modify(modRequest)
} catch {
case lde:LDAPException => println("failed LDAPException: " + lde.toString())
}
}
So, I get this as a runtime error:
Going to try to set password to [B#6dd1627e with: ModifyRequest(dn='cn=Tester Dude,ou=Lab,ou=Org,ou=Provider,DC=example,DC=net', mods={REPLACE unicodePwd})
failed LDAPException: LDAPException(resultCode=53 (unwilling to perform), errorMessage='0000001F: SvcErr: DSID-031A11E5, problem 5003 (WILL_NOT_PERFORM), data 0
', diagnosticMessage='0000001F: SvcErr: DSID-031A11E5, problem 5003 (WILL_NOT_PERFORM), data 0
')
So among the things I know can cause this error:
Not connecting via SSL. (Not the case here, and I've checked to be 100% sure I'm on port 636 using netstat)
Passing a password which violates the Active Directory password policy. (I've tested setting that exact password manually; it will reject short/simple passwords, but it accepts the one I'm using in this code)
I've tried it both with and without the extra quotes around the password.
The most useful source of info thusfar was:
http://www.dirmgr.com/blog/2010/8/26/ldap-password-changes-in-active-directory.html
But I've exhausted every suggestion there (and a lot of other places).
I've also tried several other things, including setting the password for a different valid user that was added manually. (This one was added via the sdk also.)
Other operations are working fine. I've removed the irrelevant code but I was able to search, print attributes, add, and delete a user with no problem; but this modify request fails. If I set the ModifyRequest to change some other attribute, such as the email associated, that also works fine.
connection not secure enough
Quote from: http://support.microsoft.com/kb/269190
In order to modify this attribute, the client must have a 128-bit Secure Socket Layer (SSL) connection to the server.
So even if everything else looks right, you may still get an SvcErr: DSID-03190F4C, problem 5003 (WILL_NOT_PERFORM) if the connection is deemed insecure.
lacking admin rights
A modify request may fail if you try to do a replace without insufficient rights.
dn: CN=johndoe,OU=Users,DC=example,DC=com
changetype: modify
replace: unicodePwd
unicodePwd:: base64(utf16le(quoted(password)))
-
You will get an SecErr: DSID-03150E47, problem 4003 (INSUFF_ACCESS_RIGHTS) in that case. This happens if you try to bind with an unprivileged account.
password history
Some admins like to have a long password history (e.g. last 24 passwords saved). You will get a CONSTRAINT_ATT_TYPE if you are using an old password that is already in the history.
regular user
secure the connection
use a delete-add combo.
e.g.
dn: CN=johndoe,OU=Users,DC=example,DC=com
changetype: modify
delete: unicodePwd
unicodePwd:: base64(utf16le(quoted(old password)))
-
add: unicodePwd
unicodePwd:: base64(utf16le(quoted(new password)))
-
It turns out that it has to be UTF-16LE encoded, and then converted to base64.
val newPass = javax.xml.bind.DatatypeConverter.printBase64Binary(('"'+"Jfi8ZH8#k"+'"').getBytes("UTF-16LE"))
Did the trick.
My guess is "unicodePwd: " + '"' + newPass + '"' is circumventing your encoding (as String has to be converted to bytes again and I bet it's not using the right encoding).
Try using the version of MofifyRequest that takes Modification objects and then use the constructor that takes the attributes value as bytes.
val newPass = "\"Jfi8ZH8#k\"".getBytes("UTF-16LE")
// note the dquotes inside the string
val mod = new Modification(ModificationType.REPLACE, "unicodePwd", newPass)
just like in the blog post you linked to...
I've also stumbled on this issue. I'm using Novell.Directory.Ldap.NETStandard library for C#. The issue in my case was that the password needs to be quoted. This code worked for me:
var passwordBytes = Encoding.Unicode.GetBytes($"\"{newPassword}\"");
connection.Modify(userDn, new LdapModification(LdapModification.Replace, new LdapAttribute("unicodePwd", passwordBytes)));

redirect from jsf?

I am working on application with jsp, jstl and jsf for my college project, thats being said, I am as well very new to jsf.
Everything is going great so far. However, I seems to have a problem figuring out how to do redirect from managed bean to page with dinamyc parameters.
For example article.jsp?article_id=2
Can somebody tell me how it is done ?
I been trying to use somethinng like
FacesContext.getCurrentInstance().getExternalContext().dispatch("faces/article.jsp2?article_id=" + articleId);
But get error:
javax.servlet.ServletException: #{postComment.postClick}: javax.faces.FacesException: javax.servlet.ServletException: javax.faces.component.UIViewRoot cannot be cast to com.sun.faces.application.StateManagerImpl$TreeNode
javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
I been trying to use
response.sendRedirect("faces/article.jsp2?article_id=" + articleId);
return;
But again getting an error.
javax.servlet.ServletException: Cannot forward after response has been committed
javax.faces.webapp.FacesServlet.service(FacesServlet.java:256)
Can somebody please tell me how do i redirect from managed java bean when working with jsf ?
Bellow is my code (maybe something wrong with that and thats why redirect not working).
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
String articleId = request.getSession().getAttribute("article_id").toString();
//String articleId = request.getParameter("article_id");
String authorName = request.getSession().getAttribute("user_name").toString();
java.util.Calendar calendar = java.util.Calendar.getInstance();
String commentDate = String.valueOf(calendar.get(java.util.Calendar.DAY_OF_MONTH)) + ".";
commentDate += String.valueOf(calendar.get(java.util.Calendar.MONTH)) + ".";
commentDate += String.valueOf(calendar.get(java.util.Calendar.YEAR));
ArrayList error = new ArrayList();
if(commentName.contains("<"))
{
error.add("Comment name contains illegal characters");
}
if(commentBody.isEmpty() && commentBody.contains("<script"))
{
error.add("Your message body contains illegal characters");
}
if(error.size() > 0)
{
request.getSession().setAttribute("error", error);
error.clear();
FacesContext.getCurrentInstance().getExternalContext().dispatch("article.jsp2?article_id=" + articleId);
}
else
{
Comment comment = new Comment();
comment.setCommentAuthor(authorName);
comment.setCommentBody(commentBody);
comment.setCommentDate(commentDate);
comment.setCommentName(commentName);
comment.setArticleId(articleId);
DisplayArticleIO addComment = new DisplayArticleIO();
addComment.postComment(comment);
// FacesContext.getCurrentInstance().getExternalContext().dispatch("faces/article.jsp2?article_id=" + articleId);
response.sendRedirect("faces/article.jsp2?article_id=" + articleId);
return;
}
Thank you in advance.
In case some one will run into same problem.
That's what solved my problem:
FacesContext.getCurrentInstance().getExternalContext().redirect("article.jsp?article_id=" + articleId);
Why are you using dispatch in one place and redirect in the other? This isn't the source of the problem - not returning after sending responses, however, is. Other then that, if you don't mind, I have a few friendly suggestions:
You can use DateFormat to return the comment date as you want it (it will be much cleaner).
If the errors ArrayList only contains Strings, use generics (ArrayList<String>).
What are you doing with the errors?
Your sanitation of the commentName is very dangerous. You should use whitelisting instead of blacklisting - define what you wish to accept in a comment and block everything else. Right now someone could insert an <img> tag with a src pointing to a cookie stealing page which would result in a session hijack.
After changing the dispatch to a redirect add a return below it (you should always do this. Not doing this could result in what you're seeing right now, which is that you've already sent a response somewhere else, but since you haven't returned you've reached a place where you're trying to send another).
Basically, something is already sending output to the client before you make the call to response.sendRedirect(). Once something has been sent to the browser you can't redirect or forward them to a different place.
In general, any scenarios that might result in a redirect or a forward should be handled as early as possible in the request context to insure the redirect happens before you send any data to the client. Are you doing something like calling this code via a tag in the view?
FacesContext.getCurrentInstance().getExternalContext().redirect("http://www.myUrl.com");
René

Categories

Resources