I have a situation as below:
I have 2 web applications running on Tomcat. Initially User gets logged in to the Application 1 and then. There is a link to the Application 2. On Clicking the link User should be redirected to second application.
Both applications using LDAP authentication.
Now, the problem here is second application has its own Authentication system.
So, We are planning to implicitly authenticate the user which is logged in the first system.
I have written a servlet, which gets executed when I click on link for App2 in the App1.
I am trying to use below code which should call Servlet "ldap-login" on app2 with given parameters.Parameter names are correct.
String targetURL = "http://localhost:8080/app2/ldap-login";
HttpClient client = new HttpClient();
PostMethod doPost = new PostMethod(targetURL);
//doPost.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, true);
doPost.addParameter("login_netid", "alice");
doPost.addParameter("login_password", "alice");
try {
int status = client.executeMethod(doPost);
if (status == HttpStatus.SC_OK) {
// redirect
response.sendRedirect("http://localhost:8080/app2/myPage");
} else {
System.out.println("Service failed, Response Code= " +
HttpStatus.getStatusText(status));
System.out.println("Response Body --> " + doPost.getResponseBodyAsString());
}
} catch (Exception ex) {
System.out.println("ERROR: " +
ex.getClass().getName() + " "+ ex.getMessage());
ex.printStackTrace();
} finally {
doPost.releaseConnection();
}
But I am getting Response "Moved temporarily".
Can anyone suggest me any alternate ?
A 302 Moved Temporarily response is just a redirect. It's exactly the kind of response which you would get when you do response.sendRedirect(). You can also very good get a redirect as a response to a successful login. I suggest to verify on the second application if it isn't indeed redirecting when the login is successful. You should then check if the response code is 302 instead of 200. Or, alternatively, you need to tell HttpClient to follow any redirects automatically.
Even more, if the login actually failed, what kind of response would you get from the second application? Would it throw an exception and thus return a response code of 500? Or would it just conditionally set some error message in the request scope and redisplay the JSP by a forward and thus keep a response code of 200? How would you then distinguish a 200 on a failed login from a 200 on a successful login?
Unrelated to the concrete problem, your approach will likely not work if the second application does not share the same session as the first application. A login is usually stored in the session, but you're not maintaining the session anywhere. Anyway, that's subject for a new question :)
As per the API doc, the sendRedirect call does a temporary redirect. As #BalusC mentioned, you need to handle response code SC_MOVED_TEMPORARILY or SC_FOUND.
The reason it's doing a redirect after login (or might be after any POST request) could be to avoid the Double Submit Problem. Here is another article on that one.
Related
when I want to redirect in my page to other I use this method exception:
throw new RedirectToUrlException("/login/j_security_check?j_username=" + username + "&j_password=" + pass);
problem is that this information are visible in browser. How I can send this and use POST method ?
POST redirects are a somewhat esoteric edge case with most browsers. Wicket's RedirectRequestHandler currently only supports HTTP codes 301 and 302. POST redirect would require 307, which will also show a warning to the user.
That said, what you are trying to do is inherently unsafe. Do not ever send a password back to the client.
Long story short: Wicket doesn't support this, and you shouldn't be doing this anyway.
Inside a filter I'm trying to send expired sessions back to a login page with a message that the user must login. I prefer to attach the message to the request object, rather than to the session object, so that I don't have to worry about erasing the message later.
When I use inside the filter:
catch (NullPointerException exc)
{
String message = "You must log in to access this site.";
url += "/login.jsp";
request.setAttribute("message", message);
httpResponse.sendRedirect(url);
}
The login page does NOT display the message (message is null). However, when I use:
session.setAttribute("message", message);
The message is displayed nicely on the login page.
In servlets, I have no problem attaching and displaying messages using the request object. It's only with filters that I'm noticing this difficulty.
Why is this happening, and can it be prevented? If I must use session when redirecting from a filter, what's the best way to erase the message on the JSP side?
Use RequestDispatcher instead.
I always refer anyone asking RequestDispatcher vs SendRedirect to this article on The Server Side.
See also ServletRequest#getRequestDispatcher(java.lang.String)
so you do
request.getRequestDispatcher("/login.jsp").forward(request, httpResponse);
there are a bunch of links accessing my servlet without https
As the servlet is a generic form and the http urls are generated with an random id it is difficult to use modrewrite or something like that.
Therefore I modified my servlet with code like that:
//redirect to https
String sec = servletRequest.getParameter("Sec");
String qString = servletRequest.getQueryString();
if (StringUtils.isEmpty(sec)){
try {
HttpServletResponse rsp = request.getServletResponse(true);
String PORTAL_URL = l_aliasHelper.getPath(request);
rsp.sendRedirect("https://"+servletRequest.getServerName() +PORTAL_URL+"?" +qString+"&Sec=yes");
} catch (Exception e) {
e.printStackTrace();
}
}
Now this works fine!
But, what if I want back to http because I want to avoid nagging warnings about insecure elements on other pages.
So how do I redirect to http again after the user has submitted the form?
If everything worked well the user gets displayed a response with a success message under the same URL he started.
So the cycle goes like this:
http://<somedomain>/<anypath>?<anyid>
https://<somedomain>/<anypath>?<anyid>&Sec=yes
and now it should go back maybe with a step inbetween to
http://<somedomain>/<anypath>?<anyid> <- the success message should be
displayed here
the last method before the message is displayed is
sucessmessage.render(request,response)
request and response are both appserver component specific views on all request / response related matters. They have methods like:
getServletResponse
public HttpServletResponse getServletResponse(boolean answering)
Gets the original servlet response. Note: This should be accessed
in extraordinary cases only. If the parameter is set to true all
further content procession of the runtime will be skipped. This is
only available, if the request was initiated from a servlet based
connection.
So how can the response be manipulated in a way that the form is submitted secure, but the user can go on with http on the rest of the site afterwards.
It seems like you are trying to do too much in one place. Maybe the following break down will be easier:
Specify https in the URL for the action parameter in HTML form.
Create a ServletFilter class that uses ServletRequest.isSecure() to
make sure that requests to your form action actually came in over
https. This could also be in your action servlet, but making it a filter means you can reuse it. Just make sure the secure servlets have this filter set.
In your form action servlet, simply send a redirect to the
success page over http
I used to just use Tomcat and JSP pages which I can execute query, then assign query result into the array or object then pass that data onto client side via response.
request.setAttribute("errorMessage", "this is error!!");
request.getRequestDispatcher("report.jsp").forward(request, response);
In client jsp code, I could do something like:
${errorMessage}
Then the "this is error!!" message would show up.
I want to do the same thing with REST JAX-RS GlassFish v3.
#Path("schedule/test")
#POST
#Consumes("application/x-www-form-urlencoded")
#Produces("application/vnd.ms-excel")
public Object tmpTest(String content) {
try {
//just my method to execute query and get result
Vector out = (Vector)QueryManager.executeQuery;
//if query result is empty, I want user to redirect to report.jsp page
if(out.isEmpty()) {
request.setAttribute("errorMessage", "This is error!!");
request.getRequestDispatcher("report.jsp").forward(request, response);
return null;
}
....continue code......
}
This results in mysterious exception I've never seen.
java.lang.ClassCastException: $Proxy109 cannot be cast to org.apache.catalina.core.ApplicationHttpRequest
at org.apache.catalina.core.ApplicationHttpRequest.getRequestFacade(ApplicationHttpRequest.java:1001)
at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:472)
at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:379)
at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:336)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:314)
So how can I redirect a user to report.jsp and also pass message like "This is error" ?
The client jsp expects the error msg variable to have a value:
<b>${errorMessage}</b>
That's not RESTful. You need to throw a WebApplicationException with a specific status code so that the client understands what exactly went wrong. E.g. when it's actually the server's mistake:
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
Or when it was after all client's mistake:
throw new WebApplicationException(Response.Status.BAD_REQUEST);
See also HTTP status code definitions for an overview.
The ClassCastException which you're facing is by the way occurring because the dispatched request is actually not an instance of the servletcontainer-provided implementation (in this particular case, the one of Tomcat or a Tomcat-fork). After all, you shouldn't be doing it this way. You're developing a REST webservice, not a JSP/Servlet website. It are two distinct worlds.
As mentioned before, you should try WebApplicationException.
I believe you this would give you your desired answer:
Try this:
if(out.isEmpty()) {
java.net.URI location = new java.net.URI("report.jsp");
throw new WebApplicationException(Response.seeOther(location).build());
}
I am developing a Java Application where I am implementing 3-legged OAuth using google gdata in Java. This application is registered on Google App Engine. At the first stage, I am getting the unauthorized request-token successfully. I am storing that token in session and create a link using createUserAuthorizationUrl(oauthParameters). Then on clicking the link, it redirect me to "Grant Access Page".
Now, even though I grant access, it doesn't show me this page. But, it redirects me to my callback url. However, this seems proper. But, it also doesn't add the entry under My Account. Here, I am storing the oauth_token in session.
When getting redirected, the url of that page contains oauth_token & oauth_verifier, both ! Now, on this callback url, I have a submit button & set action of for to an accessTokenServlet.java. The code of this servlet is as follow :
Now I am sending request to fetch Access Token. My code is :
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET);
oauthParameters.setOAuthType(OAuthParameters.OAuthType.THREE_LEGGED_OAUTH);
GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer());
oauthParameters.setOAuthToken(request.getSession().getAttribute("oauth_token").toString());
oauthParameters.setOAuthTokenSecret(request.getSession().getAttribute("oauth_token_secret").toString());
try {
String accessToken = oauthHelper.getAccessToken(oauthParameters);
out.println("Access Token : " + accessToken);
} catch (OAuthException e) {
//System.out.print("Response Status : " + response.getStatus());
out.println("Exception : ");
e.printStackTrace();
return;
}
While clicking on submit button, it prints "Access Token : " & nothing ! No token returns !
I am getting wrong at the stage of authorizing the request token itself. But, I am not getting, what problem got generated ?
The page with the verifier you linked to should only happen if you pass in an oauth_callback of oob — this indicates that you will be moving the verifier out-of-band. I strongly recommend against using oob for anything but debugging. Instead, you should be setting a callback URL and getting the verifier out of the query string.
In the code above, I don't see anything that sets the verifier in the OAuth parameters, so that's likely your problem. You're also not doing much in the way of error handling, and that's a really important piece of the OAuth flow — for example, once you've got it working, try canceling the OAuth process and see how your application handles it.
You will only see the entry in your issued tokens list after you've fully completed the process and obtained an upgraded access token.