I'm trying to figure out how cookies can be used to prevent a hacker from typing in a URL to an internal part of a java web application that shouldn't be accessible unless the user is logged in.
For example, I'd like to prevent a hacker from typing in http://domain.com/myapp/listtable.jsp and be able to view the table without logging in.
I have a servlet which stores a list of all cookies it has handed out to clients. I'm struggling to understand what the JSP/JSTL code would look like to examine the cookies in the request and compare it to what the server has stored.
Something like:
<c:forEach items="${cookie}" var="currentCookie">
<!-- Compare each incoming cookie with the cookies kept in the servlet,
if there's not a match then redirect to the login page. Otherwise,
show the contents of the page below -->
</c:forEach>
<html>
--- main page HTML here
Can anyone give me some advice on how to do this?
This should be the Job of Filter not of view
Configure a Filter to check for your protected resources
Check if user's session has some value that logically makes him logged in.
if not redirect user to login view
See Also
universal-login-authorization-in-jsp
why-business-logic-should-be-moved-out-of-jsp
I would personally add my JSP or any presentation content (that you deem protected) under the WEB-INF folder and map it accordingly to your controller. That way, the servlet container will hide it from external viewing.
Even it's not the correct way to do it... in fact you can do something like that.
Try this:
<c:forEach items="${cookie}" var="currentCookie">
<!-- Compare each incoming cookie with the cookies kept in the servlet,
if there's not a match then redirect to the login page. Otherwise,
show the contents of the page below -->
${currentCookie.value.name} - ${currentCookie.value.value}<br/>
<c:if test="${currentCookie.value.name=='JSESSIONID'}">
Your Session is ${currentCookie.value.value}
</c:if>
</c:forEach>
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.
I have a simple login page (login.jsp) and I'm checking it against a database to verify user credentials. This is just for testing, not for making an actual site.
In the verification servlet where the values are checked against the DB values, if there is not a match I do a
response.getRedirect("login.jsp?loginfailed=true");
This, obviously, sends me to
localhost:8080/blahblahblahblah/login.jsp?loginfailed=true
which is what I want. But then, in the jsp file, I do
<%
if(request.getParameter("loginfailed") == "true")
{
out.println("login failed");
}
%>
I'm well aware that I should replace this with JSTL, it's just easier for me to use scriptlets at first for control flow and I change them out once the logic works.
I just don't know why it is not working right now. What am I doing wrong?
Basically when credentials DO match DB values, it redirects to a success page. But if they don't, it redirects back to login.jsp with a URL param, and I want to print some text that says the login failed so the user doesn't have to look at the url to see that.
your redirection should be in this way.
response.sendRedirect(request.getContextPath()+"/login.jsp?loginfailed=true");
I want to forward from one page to another but with the same I want url to be changed. Suppose user is here http://mywebsite/register and when he completes his registration process then I want this in his address bar http://mywebsite/home
Is it possible without using sendRedirect , I mean by the way server side forwarding only? or any other way around to this problem?
You could just let the HTML form submit to that URL directly.
<form action="http://mywebsite/home">
But this makes no sense. You'll also run into problems when redisplaying the same form with validation messages in case of validation failure. You'd need to redirect back to the original page if you intend to keep the original URL and you'd need to fiddle with storing messages in the session scope instead of the request scope because a redirect basically creates a brand new request. You'll without a redirect also run in "double submit" problem whenever the enduser presses F5 after submitting the form.
Just let the servlet redirect the successful POST request to the desired URL. That's the canonical approach. Even more, this is a recommend "design pattern": the POST-Redirect-GET pattern.
AFAIK there's no way around a redirect since the browser has to update the url at some point. And if you'd update the url after the forwarded to page has been loaded it would issue a refresh and the page would be loaded again (which might result in an endless loop).
Why don't you want to use a redirect in that case?
To remove the language toggle from the page view(Comfirmation Page)
I found this code but it doesn't work in Spring MVC
<c:if test="${!fn:contains(pageContext.request.servletPath,'/comfirmation')}">
//Other Code
</c:if>
My actual url is (ShoppingCart.jsp).
It is used when /viewCart.htm,/updateCart.htm,/Confirmation.htm,etc.
So, the user go to the /Confirmation.htm, it also redirect to the ShoppingCart.jsp but the url path in the browser is /Confirmation.htm.
I want to remove the language toggle when call the /Confirmation.htm in the above mention.
Finally, I got it. Here we go
<%
String url=request.getAttribute("javax.servlet.forward.servlet_path").toString();
if(url.equals("/Confirmation.htm")){
%>
//Language Toggle code
<% } %>
I decided to use this. Another way is that storing url path in session since front controller.
the pageContext.request.servletPath will give you the path of the jsp (and not the url your browser shows).
The request is forwarded to a controller, which returns a path to a view. The view ist called using a second internal request