Hi I am new to java servlets. I was trying to implement simple shopping cart problem using cookies. In my web page I ask user to input a product name that she can add to her cart.
Web page:
Simple text input (product name)
and a Button (add to cart)
Upon clicking the button, the web page displays the cart values.
I am experiencing a strange problem. It works fine for less than 3 values. When I try to add third value, it's only displaying the most recently added two values. For example if I add products a, b and c respectively. It displays b and c only.
Cart Servlet code:
String name = request.getParameter("productname");
Cookie cookie = new Cookie("product", name);
cookie.setMaxAge(100 * 60);
response.addCookie(cookie);
Cookie[] cookies = request.getCookies();
List<String> names = new ArrayList<String>();
names.add(name);
if (cookies != null) {
for (Cookie c: cookies) {
if (c.getName().equals("product")) {
names.add(c.getValue());
}
}
}
PrintWriter writer = response.getWriter();
for (String item: names) {
writer.println("<h4>" + item + "</h4>");
}
index.jsp:
<form method="post" action="Cart">
<input type="text" name="productname" value="Product name">
<input type="submit" value="AddToCart">
</form>
I have spent so many hours to figure out what's wrong in it. but I couldn't find any mistake to explain this strange behavior. Please help.
The behavior came from the way how your client (browser) and server handle cookies with the same name.
"Several cookies might have the same name but different path
attributes."
https://docs.oracle.com/javaee/7/api/javax/servlet/http/Cookie.html
So in your case it is basically the same cookie (based on name and path) which is updated constantly.
So what happens in your case: Basically, the browser returns cookies to the servlet by adding fields to HTTP request headers. Assuming that your first product was named a and you are sending your second product with the name b, your cookie-header looks like
Cookie:JSESSIONID=BCC7050AE82AEA1A4B9BED1174424A92; product=a
and your form-data
productname:b
The server receives the request and a new Cookie is created and added to the HttpResponse cookie list. The list containing two cookies named product is correctly printed in your response. Since the servlet sends cookies to the browser by using HTTP response headers and your cookies are the same, only an update takes place.
Set-Cookie:product=b; Expires=Sat, 23-Dec-2017 11:23:53 GMT
As a consequence the next request only contains the information regarding product b and product a disappears.
I found that following piece in web.xml doesn't invalidate session even after closing the browser. Thanks to fI12 for suggesting the link of Session Lost when closing the browser.
<session-config>
<session-timeout>11520</session-timeout>
<cookie-config>
<max-age>11520</max-age>
</cookie-config>
</session-config>
Using cookies for shopping cart is not a scalable solution. Sessions are the way for this.
Related
In my ASP.NET MVC project, user can save a form on screen which makes HTTP POST request to server.
How can I prevent client to send automated HTTP POST's to server. Is there any builtin way on IIS or web.config to block unusal request rates?
For example a setting like, "based on Session ID, request count in 1 minute cannot exceed 30" could be helpful.
Captcha control is not a good option for me. Because there are many save options on screen, setting captcha for each of them will be useless.
Not quite what you asked for, but you can use session variables to limit a form from being posted unless the form is first requested, and protect against being submitted multiple times.
On your form page, generate a random number:
Random rnd = new Random();
int key = rnd.Next(100000, 999999);
Create a session variable with this number as the name, something like this:
Session["key_"+ key.ToString()] = true;
In your form add a hidden field with this number:
<input name="key" type="hidden" value="#key" />
Upon form post get the hidden field value and check that the session variable exists. Then remove the session variable so the form cannot be resubmitted:
int key = 0;
int.TryParse(Request.Form["key"] ?? string.Empty, out key);
if (Session["key_" + key.ToString()] == null)
{
//invalid post, take some action
//best to return the user to the form and give them another chance
//in case it was legitimate, eg. session timed out
}
else
{
Session.Contents.Remove("key_" + key.ToString());
}
You can use a mvc attribute called AntiForgeryToken on your post action method, It generates a encrypted value and a salt used to verify if your post is authentic.
See this link
https://msdn.microsoft.com/en-us/library/dd470175(v=vs.118).aspx
I need to check where did the incoming request came from before loading a page
ex:
for user to view www.mysite/page1.aspx
request should come through www.othersite/page1.aspx
so on page1 load in mysite i need to check whether the request came from page1 in othersite.
i have tried Page.Request.UrlReferrer but i saw there some posts which tells every browser might not support Page.Request.UrlReferrer.
i can not pass visible parameters on URL.
This is a common issue when you do not want to allow request from arbitrary sites.
What you can do is, create a variable in session and put this variable in the Page1.aspx. When the page posts back, you should get that variable back and it should also match the one stored in the session. If it does not, you can be sure that the request is from some other server.
You can use PostBackUrl on the start page
And access your parameters with PreviousPage in the arrived page
if (this.PreviousPage != null)
{
var control = Page.PreviousPage.FindControl("..."); //Adjust your Id and add cast
}
Nota : This was also created to provide greater security redirection setting.
I want to redirect a response to another URL while it contains some POST data in it's HTTP header.
// Inside an ASP.NET page code behind:
Response.Redirect("http://www.example.com/?data=sent%20via%20GET");
// This will sent data to http://www.example.com via GET.
// I want to POST this data to http://www.example.com instead.
How to do this in ASP.NET?
you can send huge data also with this trick..
Response.Clear();
StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.AppendFormat(#"<body onload='document.forms[""form""].submit()'>");
sb.AppendFormat("<form name='form' action='{0}' method='post'>",postbackUrl);
sb.AppendFormat("<input type='hidden' name='id' value='{0}'>", id);
// Other params go here
sb.Append("</form>");
sb.Append("</body>");
sb.Append("</html>");
Response.Write(sb.ToString());
Response.End();
You can't POST using a redirect. By definition a redirect means the server sending a 302 redirect HTTP status code to the client with the new location so that the client issues a GET request to this new location. That's how the HTTP protocol works and there's not mu ch you can do about it.
So one way to achieve this would be to redirect to some temporary page that will contain an HTML <form> with method="POST" and containing the values you want to send as hidden fields. Then you could use javascript to autosubmit this form.
Though it is quite old thread, I thought I would share how I do it.
Let's say sending page is a.aspx and destination page is b.aspx.
Collect user inputs in a.aspx. User clicks submit button which causes postback.
inside Button_click event of a.aspx, process volume data (for example save uploaded binary files). Determine link of the volume data and append that to end of request.form name-value string.
Encrypt the final name-value string and set it to a cookie.
Redirect to b.aspx
in b.aspx, retrieve that cookie, decrypt and you get all name-value pair. Now process them as usual.
Advantages:
(a) b.aspx is shown in browser address bar. It enters in browser's history. Server.transfer do these.
(b) It gives effect of post. Users can not see the name-value pair in querystring.
You can use viewstate to "transfer" the data and read it on a new page or even the same page.
I have very large website which uses a lot of cookies. There are approx. 14 different cookies are there. I have different cookies for each item. When a user surfs the site they will have 14 cookies in their browser. I do not want this.
I want a single cookie for my site that will have 14 items and I can add,edit and delete them. I tried many ways but I am not able to do this.
I need to put some run time cookies as well save the user name in cookie. After the user logs in I want to save their personal site address in it. Eventually I want both the user name and personal site address both. I want to save user name before and then when user goes to his personal site then i will store personal site name run time.
Does any one have an idea how I could do this?
Matthew beat me to it, but yes, see the ASP.NET Cookies Overview...
To write and read a single cookie with multiple key/values, it would look something like this:
HttpCookie cookie = new HttpCookie("mybigcookie");
cookie.Values.Add("name", name);
cookie.Values.Add("address", address);
//get the values out
string name = Request.Cookies["mybigcookie"]["name"];
string address = Request.Cookies["mybigcookie"]["address"];
There is a section in the ASP.NET Cookies Overview that discusses how to implement multiple name-value pairs (called subkeys) in a single cookie. I think this is what you mean.
The example from that page, in C#:
Response.Cookies["userInfo"]["userName"] = "patrick"; //userInfo is the cookie, userName is the subkey
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString(); //now lastVisit is the subkey
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
HttpCookie aCookie = new HttpCookie("userInfo");
aCookie.Values["userName"] = "patrick";
aCookie.Values["lastVisit"] = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);
EDIT: From the Cookies Overview (emphasis added):
Modifying and Deleting Cookies:
You
cannot directly modify a cookie.
Instead, changing a cookie consists of
creating a new cookie with new values
and then sending the cookie to the
browser to overwrite the old version
on the client.
Modifying and Deleting Cookies: You cannot directly modify a cookie. Instead, changing a cookie consists of creating a new cookie with new values and then sending the cookie to the browser to overwrite the old version on the client.
If you have a link to a webpage in a MicroSoft Word document and you follow this link to get to the web page ASP.Net session variables do not always work as expected.
In particular they work the first few times and then later on they stop working.
For instance if you have a link to an MVC Page like:
http://localhost/Home/TransferToWebForm
and in the controller you have:
public ActionResult TransferToWebForm()
{
Session["SessionVarFromMVC"] = "Some Value";
return Redirect("~/WebForm.aspx");
}
Then in the target page (WebForm.aspx) you try to retrieve these session variables they are empty.
<%= string.IsNullOrEmpty(Session["SessionVarFromMVC"])
? "***Session Empty***"
: Session["SessionVarFromMVC"] %>
(I discovered in Office 2007 and I'm not sure if the problem exists in other versions)
The problem is that when you first follow the link from Microsoft Word the server sets a cookie (ASP.NET_SessionId) and word remembers this. Subsequent clicks on the link cause the same cookie to be sent to the server with the new request.
Everything works fine with this process until that session times out on the server. On the next click Word sends the cookie with the request and the server no longer has a valid session for it. In this case the the session variables set by the first page simply fall off the end of the earth (so to speak) and are not available to the next page.
The thing that is puzzling to me is why is Word storing the session cookie?