I am new to Jmeter and load testing overall but I have read about the Cookie Manager over and over and still can't find the answer to my problem.
The site I am trying to test uses several cookies to authenticate but not all of them are seen in the Jmeter Response Headers. I can see them if I look using the browser but Jmeter doesn't seem to pick them up at all.
If I manually set the cookies in the Cookie Manager after a recent session then the test passes but my concern is that when I use multiple threads, they won't all get individual values and rather just the ones I have specified.
I expect all the cookies that are set to be displayed in the response headers, that way I can set variables etc but out of 3 only one appears in Jmeter.
Please check the below information:-
JMeter checks that received cookies are valid for the URL. This means
that cross-domain cookies are not stored. If you have bugged behaviour
or want Cross-Domain cookies to be used, define the JMeter property
"CookieManager.check.cookies=false".
Received Cookies can be stored as JMeter thread variables. To save
cookies as variables, define the property
"CookieManager.save.cookies=true". Also, cookies names are prefixed
with "COOKIE_" before they are stored (this avoids accidental
corruption of local variables) To revert to the original behaviour,
define the property "CookieManager.name.prefix= " (one or more
spaces). If enabled, the value of a cookie with the name TEST can be
referred to as ${COOKIE_TEST}.
You can find these setting under JmeterFolder/bin/jmeter.properties file.
For more information:-
Cookie Manager
Kindly check if this helps.
Related
Given a CORS API that requires a session cookie to track users as they move through a checkout process, there are issues in multiple browsers where the cookie is not set until after the user visits the site the API is hosted on.
For example:
johnny.com uses an CORS JSON API from jacob.com. jacob.com sets a
cookie after the first AJAX call is made, but some browsers will not
set the cookie for subsequent calls. Therefore the API will not
function as expected.
Browser Behavior:
Chrome seems to function fine unless "Third-Party cookies" are
deliberately disabled. There doesn't seem to be a workaround for
this.
IE does not allow the cookie to be set initially unless there is a P3P privacy policy header returned with the initial call.
Safari does not allow the cookie to be set initially unless a hack is used (see: http://measurablewins.gregjxn.com/2014/02/safari-setting-third-party-iframe.html)
Any insight on how to work around these issues is greatly appreciated.
Unfortunately, it seems there are not option to make that work across all browsers.
Safari now restricts third party use of cookies.
It seems the best is to evaluate alternatives :
Setup a proxy server that will redirect the calls to the different services (for example, when you hit johnny.com/jacob/abc, act as proxy to retrieve jacob.com/abc)
Use oauth login on API (it might be impractical)
Move the API under johnny.com/api/...
Paypal has also created several js based solutions to try to go around this kind of problems : https://medium.com/#bluepnume/introducing-paypals-open-source-cross-domain-javascript-suite-95f991b2731d
When you protect an area of your document root using either the server configuration or .htaccess, the server prompts for a username and password when someone requests those files from a browser. If the password matches the one from the authentication provider for that user, the documentation at http://httpd.apache.org/docs/2.2/howto/auth.html says that apache will set environment variables for that user. In my case I'm building a php app, and using phpinfo() I gather that the environment variables set are are REDIRECT_AUTHENTICATE_SAMACCOUNTNAME, AUTHENTICATE_SAMACCOUNTNAME (Using active directory as authentication provider), and REMOTE_USER. I believe this is what prevents the user from being prompted again and again on each subsequent request.
What I don't understand is how apache matches requests from a user with the environment variables set for that user, and also when and how it knows how to clear those variables. I doesn't appear to use cookies, because I cleared all the cookies for the domain in question, and still it doesn't ask me to reauthenticate unless I actually close the browser.
Ultimately I'm going to be working with php to get the userid and to maintain state, but since php is getting the information from the apache information, I'd like to know about that context, and I don't seem to be able to find these details. Thanks in advance.
Look at the http headers your browser is sending. After you have supplied a username and password, your browser will continue sending those details to that site until your browser session ends, or longer if you tell your browser to remember the credentials.
For a web-application, we are dependant on CMS deployed on web-logic and web-app deployed on tomcat. When user access a page, dynamic content is rendered from tomcat(sticky session is enabled) and static content(js, css etc.,) are rendered from CMS(on web-logic). This is leading to a conflict on JSESSIONID cookie. The web-logic JSESSIONID is overriding the Tomcat JSESSIONID and the user is loosing the contents saved in session, when moving to and from various parts of the site.
The request flow is as below
[1]: http://i.stack.imgur.com/17Ft5.png
As a band-aid, we wrote a rule on load balancer to drop JSESSIONID for all responses coming from CMS.
Though it worked, looking for a better way to handle this.
Why your CMS is setting a cookie? Does it need sessions to provide those files?
Usually static files do not need a session. One should allow them to be cached on proxies and on the client.
Configure your CMS appropriately. If it is a web application, you may add a Filter that removes Set-Cookie header from its responses (like you are doing on your LB).
It is possible to change the name of a session cookie. This is configurable using <session-config>/<cookie-config>/<name> element in web.xml in web applications that adhere to Servlet 3.0 (or later) specification.
(It is also configurable as sessionCookieName attribute on Context element in META-INF/context.xml, but using web.xml is the recommended way).
Note that Cookies can have a Path attribute. A browser won't send a cookie if its Path does not match the URL of the request. Cookies with Path:/web and Path:/content can happily co-exist together.
Tomcat supports requests that have several JSESSIONID cookies. It just chooses the one that matches an existing session. All the others are ignored.
I have a test plan that runs fine under http, and the Cookie Manager is correctly keeping my sessions in place. It is also capable of talking to the same server when switched to ssl, and even thinks everything is working correctly because it gets a 200 response with our custom message about not being logged in.
All I need to do to reproduce the behavior is switch from http to https. The test is still able to talk to the server, but I can see in the "View Results in Table" log that cookies has a JSESSIONID under http, and is empty under https. And each request under ssl is answered with a Set-Cookie for JSESSIONID.
Interesting scenario. Does the Jmeter log file offer any clues?
Could it be that Jmeter needs a copy of the certificate to properly store the SSL cookie? The console would display a handshake problem, which can be resolved by adding the certificate into the key store:
http://www.java-samples.com/showtutorial.php?tutorialid=210
You might be able to do some further debug by writing out the cookie value to a variable and logging its value:
Received Cookies can be stored as JMeter thread variables (versions of JMeter after 2.3.2 no longer do this by default). To save cookies as variables, define the property "CookieManager.save.cookies=true". Also, cookies names are prefixed with "COOKIE_" before they are stored (this avoids accidental corruption of local variables) To revert to the original behaviour, define the property "CookieManager.name.prefix= " (one or more spaces). If enabled, the value of a cookie with the name TEST can be referred to as ${COOKIE_TEST}.
Source: http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Cookie_Manager
Edit: Somebody asked how my specific problem was solved. It turned out not to have anything to do with ssl specifically, but that other unrelated headers changed very slightly in their format, so the regex we were using to match on them started failing. So I'd start there with looking at your headers and comparing the difference between when you post http vs https
I have an ASP.NET MVC action that sends a GET request to another server via HttpWebRequest. I'd like to include all cookies in the original action's request in the new request. Some of the System.Web.HttpCookies in the original request have empty domain values (i.e. ""), which apparently doesn't cause any issues. When I create a System.Net.Cookie using the name, value, path, and domain of each of these cookies and add it to the request's CookieContainer, I get this error:
"System.ArgumentException: The parameter '{0}' cannot be an empty string. Parameter name: cookie.Domain"
Here's some code that will throw the same error (when the cookie is added):
var request = (HttpWebRequest)WebRequest.Create("http://www.whatever.com");
request.Method = "GET";
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add ( new Cookie ( "MyCookieName", "MyCookieValue", "/", "") );
EDIT
I sort of fixed this by using "localhost" for the domain, instead of the null or empty string value from the original HttpCookie. So, why does an empty domain not work for the CookieContainer? And does HttpCookie use an empty value to signify localhost, or do I need to find another fix for this problem?
Disclaimer:
As stated earlier by #feroze, setting your cookies' domain to localhost is not going to work out so well for you. I'm assuming you're writing a helper that allows you to tunnel HTTP requests out to foreign domains. Note that this is not best practice and in a lot of cases is not needed (i.e. jQuery has a lot of cool cross-domain support built-in, also see the new CORS specification). But sometimes you may be stuck doing this (i.e. the external resource is XML only, and is on a server that doesn't support CORS).
Background Information on Cookie Domains and How They Work:
If you haven't already take a look at HTTP Cookie: Domain and Path on Wikipedia -- pretty much everything you need to know is in there.
When evaluating a cookie, the Domain and Path are taken into account by both the client (the "local" requester) and the web server (the "foreign" responder). When a client requests a resource, the client should only send cookies where those cookies match the Domain (or a more generic parent domain) and Path (or a more generic parent path) of the URI being requested.
Web browsers handle this correctly. If a web browser has a cookie for the domain "localhost" and you're requesting "google.com", for example, those cookies for the "localhost" domain won't be sent in the request to "google.com". -- In fact, most modern browsers won't just not send them, they'll completely ignore them in Set-Cookie response headers that they receive (these are called third-party cookies -- enabling the acceptance of third party cookies in your web browser is a huge privacy/security concern -- don't do it!).
It works in the other direction as well -- even though it's unlikely for a client to include a third party cookie in a request, if it does, the foreign web server is supposed to ignore it (and even some cookies for correct domains/paths, so as to prevent the infamous super-cookie issue. (i.e. The web server hosting "example.com" should ignore cookies belonging to its parent domain: ".com", because ".com" is a "public suffix")).
What You Should Do [if you have to]:
The course of action I recommend for you, is when you read in your client's cookies (I'm not an MVC guy, but in regular ASP.NET this would be in Request.Cookies), loop through them (make sure to filter out your own site's legitimate cookies, especially SessionId, etc -- or use Path properly so they never get sent to this page in the first place), then add them one at a time to the outgoing request's cookie collection, rewriting the domain to be "www.whatever.com" (per your example -- if you're doing this dynamically, load the URL into a new Uri() object and use the .Host property), and then set the Path to "/". -- This will build the "Cookie" header for the outgoing request to the foreign web server.
When that request returns to your server, you then need to check it's incoming response for new cookies -- those cookies can be repackaged and sent back down to your client in much the same type of loop as I illustrated in the previous paragraph, except you'll want to rewrite Host to be Request.Url.Host -- and you'll want to set path back to "/" unless the path to your passthru page is static (I'm guessing it isn't since you're using MVC) then you'd want to set it to Request.Url.AbsolutePath for instance.
Happy Coding!
EDIT:
Also, you'll want to set the X-Forwarded-For tag of the outgoing request, so that the website you're calling doesn't think your web server is one single client that's been spamming the crap out of them.
Not sure it solves your problem. But to add cookies without the "Domain" property you must add to the headers the cookies using HttpRequestHeader.Cookie as follows.
request.Headers.Add(HttpRequestHeader.Cookie, "Your cookies...");
Hope it helps!
Some background
This occurs because CookieContainer is client-side container designed to be reused across multiple HttpWebRequest. Reusing it provides the expected cookie behavior that cookies set by the remote host are sent back with every subsequent HttpWebRequests targeted at the same host.
As a result of the reuse, a CookieContainer might actually contain cookies from multiple request and\or hosts.
So, in order to determine which of the cookies in the container need to be sent with a particular HttpWebRequest to some host (domain), CookieContainer examines the Domain and the Path property.
That's why a Cookie in a CookieContainer needs to have a valid Domain.
Conversely, on the server-side cookies are delivered via a different type, CookieCollection which a simple list of cookies with no extra logic.
Specifically, in your case, while copying cookies from the CookieCollection to the CookieContainer you need to set the Domain property of every cookie to the domain your are going to forward the request to, so that HttpWebRequest will know to include the cookies while sending the request.
You are trying to get cookies sent to localhost, right?
Why don't you do something like this where you give your own machine a real name:
Edit your hosts file and add a line "127.0.0.1 myname.com"
Test using myname.com - which is actually your localhost.
Your browser or app will not know the difference and send cookies to myname.com if that is where the cookie belongs.
Detailed info:
The Hosts file on windows is located at C:\Windows\System32\drivers\etc\hosts