I have a JSF 1.2 login page (login.xhtml) that has 2 sub-forms - menuForm, loginForm.
Using a browser, I am able to navigate from the login page to a productList.xhtml page by clicking on the Login button within the loginForm.
....
For allowing the Google Crawler to crawl through my pages that require login, I am trying to test a form submit with a Java program on the loginForm to see if I can retrieve the productList.xhtml page.
The hidden fields (View Source from browser) in the login.xhtml page includes the following:
username
password
autoScroll
loginForm
loginButton
javax.faces.ViewState
I have submitted all the values from above (except the javax.faces.ViewState) in my Java program, but I keep getting only the login.xhtml page back in my response. Why is this?
I cannot submit the javax.faces.ViewState because there is no state on the server-side for the form when a submit happens from the Java program. How do I submit a form that does not yet have a view state?
For allowing the Google Crawler to crawl through my pages that require login
A login requires a session (basically: a cookie). But web crawlers does not maintain the session (basically: they do not maintain cookies). So it ends up here. You have to remove the login form and replace all navigation commandlinks by normal links in order to let any webcrawler index your pages.
It's by the way beyond me why you would like to make restricted pages crawlable (thus: publicitly available). Why is the login there in first instance?
I have submitted all the values from above (except the javax.faces.ViewState) in my Java program, but I keep getting only the login.xhtml page back in my response. Why is this?
Because you omitted the view state field. JSF won't process the form submit then. For a part, this is a safeguard against CSRF attacks and for other part, this is because JSF is a stateful component based MVC framework.
I cannot submit the javax.faces.ViewState because there is no state on the server-side for the form when a submit happens from the Java program. How do I submit a form that does not yet have a view state?
You need to either maintain the session (basically: send all cookies from the server back in subsequent requests), or to set the state saving method in web.xml to client and you also need to pass the view state hidden field along with the form submit request.
Related
I am in bit of a delicate situation here. In my organization we design stock management systems and it is a web application based on JSP pages and servlets which handles them.
I have been asked to fix a specific problem. We have a JSP page with an HTML form table where there are stock details. When user enters the details manually and submit the form, stock details updated in the database and it works fine.
Problem is this : When the user press the browser's back button, user can come to the previous page where he submitted the details. And when the user submit this, data is saved once more to the database.I need to prevent this behaviour.(Something likeclear and reload the page.)
Things I did so far : clear the browser cache.Code works fine but not the expected result.
Unfortunately I cannot share the code due to company regulations. What I need is a help to prevent this behaviour or a workaround.
Thanks in advance..
You can use a javascript function with the help of a hidden attribute to reload the web page. When the user press the back button,based on the value of the hidden attribute, page will be reloaded without loading the cached page.
Your approach of clearing cache is correct. Coupled with that, you can use this approach.
<input type="hidden" id="refreshed" value="no">
<script type="text/javascript">
onload=function(){
var e=document.getElementById("refreshed");
if(e.value=="no")e.value="yes";
else{e.value="no";location.reload();}
}
</script>
One drawback of this approach is if your clients' browsers have disabled JS, this will not work.Otherwise it should work.
When the user press the browser's back button, user can come to the
previous page where he submitted the details. And when the user submit
this, data is saved once more to the database.
According to how you described it, that is based on a doGet request. Which means every time you visit that URL, it will send the request with whatever parameters were added.
As someone already mentioned, if you switch the form to a post method and switch the Servlet to a doPost, you won't have this issue anymore.
Alternatively you can circumvent this with a javascript solution. Here are some options:
You can check if the user clicked the back button, disable form if true.
Another way is by storing a cookie which you check on page load, if it exists you can disable the form.
You can use this code also
$(document).ready(function() {
function disableBack() { window.history.forward() }
window.onload = disableBack();
window.onpageshow = function(evt) { if (evt.persisted) disableBack() }
});
You must use a Post-Redirect-Get pattern: https://en.m.wikipedia.org/wiki/Post/Redirect/Get.
Actually, every use of standard HTML forms with method="post" should be implemented with that pattern. It doesn't have any use for AJAX-posted forms, which actually could be another solution but will require more work and probably some architectural changes.
I had this same problem while building a django web app, and my solution was to not allow caching of the html that contains the form. In your request handler, do not allow the browser to cache the page. This will force the browser to get the page fresh from the document.
Which, in this case, you can just verify in your request handler if the requested form has already been submitted.
My code for reference:
from django.views.decorators.cache import never_cache
#never_cache
def GetForm(request, pk):
# Logic #
if (IsFormCompleted(pk)):
# Handle request #
Here is a solution.
give a random id in a hidden field on the form. Then on the server side, if the user resubmit, check if the random id already on the database. If so, redirect user.
I have a search.jsp page that has some html content and a form. When the form is submitted, there is a servlet handle the form data and forward the results to the search.jsp page. However, the url in the browser after processing the form is changed to the servlet name:
http://localhost:8080/MyProject/SearchServlet
not the search.jsp page:
http://localhost:8080/MyProject/Search.jsp
How I can change the url to the search.jsp? In other words, I just want to refresh the search.jsp page to display the results in the same page. How I can do that?
You cannot do that by forwarding the request: you need to "tell" the browser to generate a new http request by using the response.sendRedirect() method.
Now the question is why do you want the url bar to display the name of the Jsp?
Hiding the real destination path is a desired feature when forwarding requests: users do not need to know the server side redirects (that's how they are also called) happening in your web app.
Think about it: to carry out its tasks a servlet potentially can forward the request a number of times before getting to the final destination: you don't want the url bar to change each and every single time.
Give a fancier name to your servlet like: "Search" rather than "SearchServlet" so that users will know they are on the search page of your web application and not in the "SearchServlet" page.
In addition to that, if you visit any professional website, you will hardly ever see the .jsp or .html or .php extension on the address bar. While that is not a requirement or specification and you are free to do so, I believe the first approach is best practice (it looks even better to me honestly). There is even a folder WEB-INF whose purpose is to hide your .jsp pages from direct access via url bar.
What I like doing is having a servlet as the landing-welcome page of the web app, that will be responsible to forward and redirect requests based on the user input and the inner working of the application.
Now back to your final request (pun intended)
"In other words, I just want to refresh the search.jsp page to display the results in the same page. How I can do that?"
What I would do is:
redirect the user to the "Search" servlet from the welcome/home servlet.
In the doGet method of the Search servlet I would forward the request to the search.jsp page (you could set attributes before forwarding if you need to).
In the search.jsp I would set the action attribute of the form to "Search" (the name of the servlet) and the method to POST.
In the doPost method of the Search servlet you would implement whatever logic you wish to implement and finally forward the request to the search.jsp
After hitting the search button (and even after the submit button is clicked) what the user will see on the address bar is simply
http://localhost:8080/MyProject/Search
Hope that makes sense.
Are you using the same search.jsp for searching and well as showing the result? It is possible to use the same jsp to perform both the functions but it's easier and desirable to make another jsp which will only show the results.
If you are not able to see the results on search.jsp then make sure that you are setting the proper response in the Servlet class before forwarding it to the jsp and also whether you are reading the response sent by the Servlet class properly in the jsp.
If you want, the page to not refresh at all, then go for AJAX.
Hi all I've got some jsp pages and im using struts2 to handle my forms.
After submitting a form by user, the url shown in address bar becomes somthing.action, so when the user refreshes the page, the forms gets submitted again. How can I handle this? after submission of a form.
If the goal is to prevent duplicate submission of forms then use token interceptor http://struts.apache.org/2.x/docs/token-interceptor.html or tokenSession interceptor http://struts.apache.org/2.x/docs/token-session-interceptor.html.
If you simple want to refresh the page after submit without submitting again then redirect to action where you only show results not form. Use redirectAction result for that.
+1 to both the other answers.
Post/Redirect/Get is the classic Pattern for every web technology.
Token Interceptor is another way to go, when you are using Struts2;
There is a third way to go, if you don't care about retro-compatibility with old browsers, or browsers with Javascript disabled: HTML5's window.history.pushState.
Just reset the url to the original one after the page is loaded, and pressing F5 will get the original page, instead of re-submitting the request.
$(document).ready(function() {
window.history.pushState("","", "myOriginalUrlWithNoParams");
});
POST REDIRECT GET
This pattern needs to be followed to prevent re-submission of form on refresh. This means, after submitting a POST request, POST should send a REDIRECT response to fetch the destination page using GET. With this pattern, if the user refreshes the page, only the GET request happens again, so the same page is fetched without updating anything in server.
This is a common design pattern recommended for web. Google would provide a lot of resources about this.
In my web application
1.1I have to close the session when the user abruptly close the browser.
1.2. When the user tries 'open in a new tab' - The user should be forwarded to the 'login page' in the new tab
I am planning to use JAVASCRIPT and AJAX to implement this in JSPX.
Can any one share any sample code to implement he above as I am new to javascript/ajax?
This can be achieved by adding the following META tags in the HEAD of your HTML. These tags will clear the cookies when the window is closed. hence the user need to relogin the next time.
<meta http-equiv='cache-control' content='no-cache'>
<meta http-equiv='expires' content='0'>
<meta http-equiv='pragma' content='no-cache'>
1.1I have to close the session when the user abruptly close the browser.
There is no reliable way to track it, you could continuously poll to server using AJAX, and if you stop receiving the ajax call consider that browser has been closed
Or call a javascript method that signals your server about close, but this will not work on weird shutdown/crashes
1.2. When the user tries 'open in a new tab' - The user should be forwarded to the 'login page' in the new tab
If user is logged in, and you want to manage another session of browser's new tab, that is not possible, because browser manages cookies centrally (amongst all tabs and window). so when it sends the request it will add the cookie in the header so your application will not be able to identify,
If you manage session using other technique like jSessionId in url parameter it is possible to do but not a 100% sure way because user can play with sessionID
Hi all
I've got some jsp pages and im using struts to handle my forms.
After submitting a form by user, the url shown in address bar becomes somthing.action, so when the user refreshes the page, the forms gets submitted again.
How can I handle this?
after submission of a form, Is there any possible way to show a ".jsp" url instead of a ".action" in the address bar?
Yes, use redirect-after-post. Either response.sendRedirect("foo.jsp"), or see here or here (depending on what exactly your code is).
If you are using Struts 2, it has a Token interceptor, to prevent duplicate form submissions -
http://struts.apache.org/2.1.2/struts2-core/apidocs/org/apache/struts2/interceptor/TokenInterceptor.html
And an example: https://cwiki.apache.org/WW/token-interceptor.html
If you redirect user to some page (it can by same as form) after you make action, it will not send post data if page will by refreshed.