tracking page request with servlets and jsps - java

If a user goes on get_appointment.jsp but is redirected, by a servlet, to the login.jsp (as he was not logged in). After successful log in, he should return to the get_appointment.jsp, as the initialization was being done from there.
Now what machanism should be used to track that from which page the request originally came, may be got forwarded to different jsps and servlets and then the user should return to the original (initial page) again.
whats the most common and better way , in general rules. is there any one for the current senarios i explained? there are many, session attributes, url rewriting, global and application, servlet context.
what if user manually changes the address bar and goes to some other place. the session attribute then make him land some time later to some incorrect page.
whats a proper way?.................
for sessions. if iam in verfiycreds.java . is there a way to get the page addres from which the request was sent to verifycred.java (i.e login.jsp)?

You could save it in the user's session...
doGet(HttpServletRequest request, HttpServletResponse response) {
// Could also be doPost(), depending on which you need.
// Request and response are both abailable there as well.
...
HttpSession session = request.getSession();
session.setAttribute("referralURI", request.getRequestURI());
...
}
You can then retrieve the URI with request.getSession().getAttribute("referralURI").
If you want to avoid sessions, you could also pass the relevant portion of the URI as a get parameter to the login.

In spring-security, the request is saved at the point, where the request gets intercepted, because it is unauthorized - in the ExceptionTranslationFilter. After successful authentication, the success-handler SavedRequestAwareAuthenticationSuccessHandler/API will be called. This handler redirects to the URL of the request, previsouly stored in the HttpSession by the ExceptionTranslationFilter.
To answer your question, this is a proper way. Look at the way they implemented it, look at the patterns, check out the code.

Related

Unable to redirect to another page in AEM using request dispatcher in sling servlet via POST

I have a scenario where from one page in AEM, I need to call another AEM page in the same application and I need to pass some hidden parameters. I choose to do it via POST and below are the steps which I followed:
From page "A", I did a form submission via POST to the sling servlet and passed some parameters.
2. In the servlet, using request dispatcher I redirected the same request and response to a different page in doPost method using the following code snippet:
request.getRequestDispatcher("/content/company/en/apps/welcomepage.html").forward(request, response);
When I run the code, I am able to call the servlet through form submission but I am not able to redirect to a new page. I see the below error in logs:
18.10.2017 14:41:00.802 ERROR [127.0.0.1 [1508352060795] POST /bin/rap/welcomepage HTTP/1.1] org.apache.sling.servlets.post.impl.operations.ModifyOperation Exception during response processing.
javax.jcr.nodetype.ConstraintViolationException: No matching property definition: appointmentTypeId = platform001d
at org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate.setProperty(NodeDelegate.java:522)
at org.apache.jackrabbit.oak.jcr.session.NodeImpl$35.perform(NodeImpl.java:1375)
at org.apache.jackrabbit.oak.jcr.session.NodeImpl$35.perform(NodeImpl.java:1363)
at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.perform(SessionDelegate.java:208)
at org.apache.jackrabbit.oak.jcr.session.ItemImpl.perform(ItemImpl.java:112)
at org.apache.jackrabbit.oak.jcr.session.NodeImpl.internalSetProperty(NodeImpl.java:1363)
If I try the same code in doGet method it works fine. Also if I use response.sendRedirect("/content/company/en/apps/welcomepage.html") it works fine too. But the problem with this is it initiates it as a new request to the page and it looses all the parameters which I get from the form submission. Could someone please let me know like how can I redirect a request to a page in AEM via POST since I need to pass some hidden parameters whic should not be visible in the url ?
Here is the way I understand your question
User visits page "A"
User fills a form, then submits.
Your custom servlet handles the submitted POST request and calls:
request.getRequestDispatcher("/content/company/en/apps/welcomepage.html").forward(request, response);
You get the ConstraintViolationException
Why do you get this exception?
Since you are using forward the POST request is forwarded to /content/company/en/apps/welcomepage.html that node is most likely of type cq:Page, which has constraints on which properties can be added. Think of it as a simple post request trying to store parameters on the cq:Page node.
What can you do?
Since I don't understand your use-case and particularly why you need to preserve the submit params, I cannot recommend a specific solution. However, since you don't want the parameters in the URL, here is a potential solution you can try:
In your servlet handler, see those hidden params to cookies on the response.
use response.sendRedirect("/content/company/en/apps/welcomepage.html")
On any of the components in /content/company/en/apps/welcomepage.html, you can get the request cookies and process them however you like. same way you wanted to process those hidden params.
Now the flow becomes:
User visits page "A"
User fills a form, then submits.
Your custom servlet handles the submitted POST request, adds your special params to cookies on the response, then calls response.sendRedirect("/content/company/en/apps/welcomepage.html")
User's browser receives a 301 response with the cookies, sets the cookies in the browser then requests "/content/company/en/apps/welcomepage.html"
Your components handle the request and get the params from the cookies, then retuns the appropriate response.

webpage authentication in jsf

I'm having a problem in identifying a session timeout page and a page navigated directly...
user will first fill a form and submits it, based on the search he will land on information page. for some reason if he try to type the url of information page instead of coming through search page how can i restrict him?
i tried using an indicator varaible in session, but that is getting in conflict with session timeout.... how do i differentiate if it is session timeout or direct navigation?
could someone please shed some light on this and point me in right direction?
From my understanding your question is:
User should not be able to access a certain page say Page1.xhtml directly. He should first fill in a form on page2.xhtml and then should be directed to this page by the server itself.
Solution:
You could put the page1.xhtml inside web-inf directory of your webapp, which will restrict direct access to your webpage.
You could you use securityConstraint tag of the web.xml and make use of container security to restrict direct access.
You could test for a server side session timeout as follows:
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
// The session has been timed out (or a hacker supplied a fake cookie).
}
The request is here the HttpServletRequest which you can obtain in the JSF context from the ExternalContext#getRequest() or, actually better, inside a Filter by just downcasting the ServletRequest argument.
As a completely different alternative, you could also introduce a timed ajax poll as a "heartbeat" so that the session never expires as long as the user has the page open in the browser.

Spring MVC strange behavior

I have a method that handles request with a URI of "/home". This request is generated upon successful log-in procedure. Here is a little code to support my situation:
<security:form-login login-processing-url="/static/j_spring_security_check"
login-page="/login" authentication-failure-url="/login?login_error=t"
default-target-url="/home"/>
The method body demonstrates what I am attempting to achieve:
String userMail = SecurityContextHolder.getContext().
getAuthentication().getName();
logger.info(userMail);
Person p = userService.retrieveUserByEmail(userMail);
session.setAttribute("person", p);
return "user/home";
This bit is important as the person p is used as data source for other requests.
Now the problem. I don't know if it is the property of Google Chrome, but for some reason the browser remembers the request you've done before log-in and instead of going through /home request after successful log-in procedure, it generates the previous request bypassing this /home gate, resulting in null pointer exception as person p was never set up, as session wasn't populated by /home request.
I know that for other requests I should do validation, but I don't like the idea of letting user generate any request without prior going through /home .
Done with text description and now to explain how I get unwanted behaviour in steps:
ask for request that you know exist such as:
myApp/nameOfSomething/viewThisSomething - you are brought to log-in page as expected(you must be authenticated for request to be accepted)
you enter correct credentials and instead of going to default-target-url="/home"
you are automatically making previous request myApp/nameOfSomething/viewThisSomething without populating session with necessary data and resulting in nullpointer exception.
What else is interesting is that logger shows the mail, so it might be that they are both executed at the same time but /home request is slower - can that happen?
I resolve the situation in other method by checking if null and forcing to go back to /home which works as expected, but I am control freak and don't like when user is doing what he is not intended to do.
Thank You for Your time,
It's not a bug, it's a feature. It's much more user-friendly to let the user go where he wants to go after login than forcing him to go to the home page. He could have bookmarked one of the protected pages, or simply browsed some non-protected pages containing a link to a protected page.
From http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-form-target:
If a form login isn't prompted by an attempt to access a protected
resource, the default-target-url option comes into play. This is the
URL the user will be taken to after successfully logging in, and
defaults to "/". You can also configure things so that the user always
ends up at this page (regardless of whether the login was "on-demand"
or they explicitly chose to log in) by setting the
always-use-default-target attribute to "true"
IMHO, you should keep things as is, but make sure that the required sesion attribute is set once the login is successful, instead of setting this attribute in the home page. This would ensure that every protected page has access to the session attribute, even if the user didn't go to the home page.
You could do this easily by using a custom UsernamePasswordAuthenticationFilter subclass, that sets the appropriate attribute in session once the authentication has succeeded.

Java Web App Security using Cookies

I'm finishing a Cattle Drive assignment where a small Java web application manages a movie library for the client. The assignment is to put some security on the application using cookies, so that a "hacker" couldn't just guess one of the URLs that would lead to another part of the application. The user will be directed to login to the site and not be allowed to view other pages until logged in.
The parts of the web app are:
1. index.html
2. VideoServlet
3. listvideos.jsp
4. addvideo.jsp
5. videologin,jsp
The entry point is request URL http://localhost:8080/videos, which loads the index.html file. This page just has a link which redirects the user to the VideoServlet. From there, the servlet forwards the HTTP request and response to listvideos.jsp, which has a link to add videos if the users wants to do that.
I'm having trouble understanding how to implement the security using cookies, while keeping everything in the MVC2 pattern (the servlet is the controller, the jsp's are the view).
Here is the program flow I came up with, but I think I'm missing the point somewhere:
user enters URL http://localhost:8080/videos, which pulls the index.html file by default.
the index.html file basically sends an HTTP Get to VideoServlet. The servlet somehow knows the user isn't logged in yet, so forwards the request/response to the videologin.jsp.
a login is presented and asks the user for a password (this is a standard html form). The user enters the password and clicks submit. This sends an HTTP Post to the servlet.
the servlet checks the password and if correct, the user is logged in and the servlet forwards to listvideos.jsp.
I don't get where cookies come in or how they can help prevent a hacker from guessing a URL and gaining direct access to, for example, addvideos.jsp. Is a cookie being used to verify if the user has already logged in?
Cookies are some plain text values (stored in text files in browser cache normally) that you could use to store data on client side. When the user makes a request to a particular URL, all cookies stored on that server (domain) are passed with it, so that the server can read up those values.
In Java, you can set a cookie like this in your servlet (in your case, when user logs in, create a cookie and store a value in it (ex. username=josh). You could do this in your login servlet after a successful login.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Verify login, and get the username. Assume it's josh
Cookie cookie = new Cookie("username", "josh");
cookie.setMaxAge(60*60*24); // 24 hours for expiry
response.addCookie(cookie);
}
Later on, you can check for the existence of the cookie and if it exists, then the user has logged in. If not, you can send a redirect to the login page.
You can check for cookies like this in your servlet.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
String username = null;
for (Cookie c : cookies) {
if ("_username".equals(c.getName())) {
username = c.getValue();
break;
}
}
if (username == null) {
// Not Logged in. Redirect to Login
}
// User Logged In. Proceed
}
Instead of putting this code in all your Servlets + JSPs, you can easily put this into a Servlet Filter class. You can read up on more on that here: http://javaboutique.internet.com/tutorials/Servlet_Filters/
Ideally, you could provide a Logout feature also, which will remove the value assigned to the username cookie by replacing it with null.
I showed the above example because you mentioned that you need to use cookies for your assignment. But if you can, try to use the Sessions (which in turn uses cookies most of the time) to store logged in user details. With sessions, you can use session timeouts to ensure that idle users will be automatically logged off after a while and so on.
the index.html file basically sends an HTTP Get to VideoServlet. The servlet somehow knows the user isn't logged in yet, so forwards the request/response to the videologin.jsp.
The somehow knows is due to looking for the presence of the cookie in the request. Make sure the contents of the cookie are protected by a message authentication code, so you can be sure that your server actually handed out the cookie. It'd also be a good idea to encode into the cookie the specific IP address being used by the client, so an attacker can't hijack a cookie. (If a client changes IP address during a session, requiring them to log in again isn't horrible. Maybe annoying, but not unexpected.)
the servlet checks the password and if correct, the user is logged in and the servlet forwards to listvideos.jsp.
the user is logged in -- set the cookie into the browser for future requests.

Java: Session attribute is only in next operation

I'm posting some strings in my Session with the call
request.getSession().setAttribute(key, value);
And making the redirect with
response.sendRedirect(urlRedirect);
In almost all cases the values is there after the redirect.
But sometimes I can only read this value in the next page view, not in the redirect. There is no common behavior.
Someone has faced the same problem?
Sessions are backed by a HTTP cookie. On first-time session creation, a cookie will be set in the response header. By default, cookies are bound to a specific context only.
So, if you redirect while the cookie hasn't been set yet, the session will get lost. To go around this, you need to encode the redirect URL.
response.sendRedirect(response.encodeRedirectURL(url));
This appends the jsessionid identifier to the URL which allows the servletcontainer to locate the right session without help of a cookie.
If you don't like the jsessionid thing, then consider implementing a filter like this which ensures that the client is aware of the session cookie before the request enters your controller wherein you fire the redirect.
Also, if you redirect to a different context, it won't be able to access the same session. To go around this, you need to configure the servletcontainer to share the session among the contexts. In for example Tomcat, check the emptySessionPath attribute of the <Connector> element in /conf/server.xml.
Such a behaviour can be caused by caching.
If the page you are redirecting to is retrieved from the browser cache, you obviously can't see the result of setAttribute() on it. So make sure it's actually requested by the browser.
Are you sure you need to do redirect through browser (response.sendRedirect()) and not on the server side (RequestDispatcher.forward())? Latter is faster as there are no network round trip.
The problem was solve by changing the way of submit.
The page was submitting the data only changing the value of location.href to the Servlet Action.
We only call the submit function from the page form, and the session attributes works fine!

Categories