I'm making log in test in JMeter and i have a problem. I made a HTTP Request as a POST method and it works - I get a JavaScript response (new popup). So the next step is another HTTP Request which return the page after log in. But instead of getting this page in return, I got another page which informs that session doesn't exist.
What is wrong?
Make sure you add HTTP Cookie Manager to your Test Plan
Make sure you detect and handle all dynamic parameters in some cases for security or state management or whatever server expects some extra parameters in addition to credentials and in case of missing or mismatch with expected logic can fail. So the test should look like:
GET request to the login page
Extract dynamic parameters and store them into JMeter Variables
POST request to login page (pass credentials and dynamic parameters)
See How To Use JMeter For Login Authentication guide for more detailed explanation and example.
Add HTTP Header Manager and HTTP Cookie Manager to your test plan. Session IDs needs to be managed.
Thanks!! It helps with log in but I have simmilar problem going further. After log in I can see a desktop with some icons. Clicking on one of this icon open a PopUp in JavaScript. I looked at POST methods - one of them has a JS code which open this PopUp as a POST response. I added it to my Test Plan. But instead of getting a js response like " new Window ({...." I receive object.SessionTimeOutAlert()". I think that this is a common problem. But now I have HTTP Header Manager and HTTP Cookie Manager and nothing....
I have the same issue. The authentication cookie was not sent and the request body shows "unauthenticated_session=deleted" under Cookie Data instead of the token values.
I resolved it by adding additional forward slashes in path by trial and error method. Some endpoints (javascript based http requests) work with // and some with /// or ////. Weird but works for me.
Related
I have an ExpressJS app with some routes that I don't want to work when typed into the url, they should work only when I redirect to them from my code.
Meaning, if an user types "myapp.com/url" it should not work. But if I add res.redirect("/url") in my code, it works
basically you can't prevent a client from sending an HTTP request to an endpoint (you can't make it "not work"). Having said that your requirements aren't that different from a login logic using JWT.
You can use JWT to set which endpoints the client can gain access to. If the client is not permitted you will redirect him to a different page.
See: https://github.com/auth0/express-jwt
Update (see comments):
when submitting the form you should generate a UUID for the request. This UUID will be a token that represents a temporary resource (video).
This is how the API will look more or less.
POST /submit
GET /generated/:UUID
GET /download/:UUID
You will need to implement some logic that will manage this temporary resource.
This is not possible as res.redirect (https://expressjs.com/en/4x/api.html#res.redirect) accept the routes which are already available via URL. If you don't want to publish the route to the outside world, you might do some sort of authorization before displaying or sending data.
login in issue: On running jmeter script recorded through workbench scriptrecorder, getting an error java script is not enabled, not able to complete test. tried to disable cookie manager still login is not working. getting message page got refreshed before navigating to next page. getting login screen only under listener view results tree view.
steps that i did: created test plan, added thread gp, added config element cache manage, cookie manager, HTTP default then added recording controller
recorded script via workbench recording controller.
tried same script via transactional controller and blazemeter recorder.
All scripts are failing at same point. login is not happening so not moving any further.
Any help would be appreciated. thanks
Record and replay will not work in the majority of cases, modern web applications are quite complex and they use dynamic parameters for different reasons, i.e. for page-level state management or security reasons. So if you record this parameter and will try to re-use it while replaying it will not work.
The process of handling dynamic parameters in JMeter is known as correlation and looks like:
Record your scenario 2 times
Compare 2 scripts to identify any dynamic values (don't forget to look not only into HTTP Request parameters, but inspect request headers as well, it can be done using View Results Tree listener)
Once you identify the dynamic parameters you will need to extract them from previous response, convert them info JMeter Variables and add them to the next request. You can consider using the following test elements for extracting the dynamic values from the responses:
Regular Expression Extractor - when response is text-based
CSS/JQuery Extractor - when response is HTML
XPath Extractor - when response is XML, XHTML or HTML
JSON Extractor - when response is JSON
Validate variables values using Debug Sampler and run the whole test to ensure that it is doing what it is supposed to be doing.
I have a design issue with my SPA, and hope someone can give me some direction. A user profile page is rendered like this:
The browser fetches /some-username.
The server checks to see if the request was a XMLHTTPRequest or not. It is not, and so it simply returns the bundled javascript app to the browser to execute.
The javascript bundle is executed in the browser, it sees the current URL and makes an AJAX request, again to /some-username.
The server sees the XMLHTTPRequest header, looks up the user who has the custom URL "/some-username" and returns the JSON data about the user back to the javascript to render.
This feels wrong. The app should be making RESTful requests to /users/:id to fetch the user data. But how can it know the id that corresponds to the user with the URL /some-username?
It is worth adding an extra HTTP request just to look up the resource identifier? Something like /get_user_id?url=/some-username.
Are you flexible about your API? If so you may change /some-username to /user-id or if you want to include username /user-id/username but ignore username.
As alternative it is also common to make requests in a filter form. Like /users?username=peter
And feel free to use /users/peter if your username identifies the user. Becuase it's actualy the id (that doesn't have to be integer) and then your url is exactly /users/:id
There is nothing "unRESTful" about /some-username. It's just another resource. The response - I hope - contains the canonical URL /user/id anyway, either as a header or as some kind of "self" link.
That's also how you could achieve your goal. Embed the URL in the page either as JavaScript or as a header equivalent (unfortunately you cannot read the headers of the page request with JavaScript):
//header. Can also use a custom header like X-User-Location
<meta http-eqiv="Location" content="/user/id">
//JavaScript
<script>
var userURL = '/user/id
</script>
I recommend keeping your current approach.
I'm creating a chrome extension, and want to be able to get a profile picture from a username. Unfortunately, there isn't an api for the website and there is no correlation between the profile URL and the profile name. I figured I could hijack the search ajax and use it to achieve my goal. Unfortunately, it doesn't seem to be working. I've added the permissions, and it isn't running in a content script, but it's still not working.
$.getJSON("http://www.website.com/user/search",{user:name},function(a){
alert(1);
alert(a.data);
});
It's failing silently, as nothing is happing. Yet, I can't figure out why.
The json I should be receiving from the call (browsed to the site manually) is:
{"error":false,"action":null,"one":true,"data":143217}
Unfortunately it's not working. JSONP isn't an option, as the site obviously has no need of supporting it, so help me please. I don't see what I'm doing wrong.
EDIT: I see the problem. When I try to do the request I'm being redirected to user/search ( no ?user) which fails.
The site you're trying to reach requires authentication before allowing a search to occur. You won't get a response from your ajax request, because the server is looking for a session with login credentials to allow the search to happen. Because your ajax is not authenticated, and does not have the session established, your request doesn't "fail", it is simply getting the server's 302 redirect response.
You would need to 'sign in' to the page you are trying to query in order to establish the session and any necessary variables before you would be able to proceed with your user search.
It could be entirely possible that the website's search API isn't returning the Content-type header as text/json, which is required for $.getJSON to function correctly.
Try simply using $.get and calling JSON.parse on the returned data.
I have a JSON web service to return home markers to be displayed on my Google Map.
Essentially, http://example.com calls the web service to find out the location of all map markers to display like so:
http://example.com/json/?zipcode=12345
And it returns a JSON string such as:
{"address": "321 Main St, Mountain View, CA, USA", ...}
So on my index.html page, I take that JSON string and place the map markers.
However, what I don't want to have happen is people calling out to my JSON web service directly.
I only want http://example.com/index.html to be able to call my http://example.com/json/ web service ... and not some random dude calling the /json/ directly.
Quesiton: how do I prevent direct calling/access to my http://example.com/json/ web service?
UPDATE:
To give more clarity, http://example.com/index.html call http://example.com/json/?zipcode=12345 ... and the JSON service
- returns semi-sensitive data,
- returns a JSON array,
- responds to GET requests,
- the browser making the request has JavaScript enabled
Again, what I don't want to have happen is people simply look at my index.html source code and then call the JSON service directly.
There are a few good ways to authenticate clients.
By IP address. In Apache, use the Allow / Deny directives.
By HTTP auth: basic or digest. This is nice and standardized, and uses usernames/passwords to authenticate.
By cookie. You'll have to come up with the cookie.
By a custom HTTP header that you invent.
Edit:
I didn't catch at first that your web service is being called by client-side code. It is literally NOT POSSIBLE to prevent people from calling your web service directly, if you let client-side Javascript do it. Someone could just read the source code.
Some more specific answers here, but I'd like to make the following general point:
Anything done over AJAX is being loaded by the user's browser. You could make a hacker's life hard if you wanted to, but, ultimately, there is no way of stopping me from getting data that you already freely make available to me. Any service that is publicly available is publicly available, plain and simple.
If you are using Apache you can set allow/deny on locations.
http://www.apachesecurity.net/
or here is a link to the apache docs on the Deny directive
http://httpd.apache.org/docs/2.0/mod/mod_access.html#deny
EDITS (responding to the new info).
The Deny directive also works with environment variables. You can restrict access based on browser string (not really secure, but discourages casual browsing) which would still allow XHR calls.
I would suggest the best way to accomplish this is to have a token of some kind that validates the request is a 'good' request. You can do that with a cookie, a session store of some kind, or a parameter (or some combination).
What I would suggest for something like this is to generate a unique url for the service that expires after a short period of time. You could do something like this pretty easily with Memcache. This strategy could also be used to obfuscate the service url (which would not provide any actual security, but would raise the bar for someone wanting to make direct calls).
Lastly, you could also use public key crypto to do this, but that would be very heavy. You would need to generate a new pub/priv key pair for each request and return the pubkey to the js client (here is a link to an implementation in javascript) http://www.cs.pitt.edu/~kirk/cs1501/notes/rsademo/
You can add a random number as a flag to determine whether the request are coming from the page just sent:
1) When generates index.html, add a random number to the JSON request URL:
Old: http://example.com/json/?zipcode=12345
New: http://example.com/json/?zipcode=12345&f=234234234234234234
Add this number to the Session Context as well.
2) The client browser renders the index.html and request JSON data by the new URL.
3) Your server gets the json request and checks the flag number with Session Context. If matched, response data. Otherwise, return an error message.
4) Clear Session Context by the end of response, or timeout triggered.
Accept only POST requests to the JSON-yielding URL. That won't prevent determined people from getting to it, but it will prevent casual browsing.
I know this is old but for anyone getting here later this is the easiest way to do this. You need to protect the AJAX subpage with a password that you can set on the container page before calling the include.
The easiest way to do this is to require HTTPS on the AJAX call and pass a POST variable. HTTPS + POST ensures the password is always encrypted.
So on the AJAX/sub-page do something like
if ($_POST["access"] == "makeupapassword")
{
...
}
else
{
echo "You can't access this directly";
}
When you call the AJAX make sure to include the POST variable and password in your payload. Since it is in POST it will be encrypted, and since it is random (hopefully) nobody will be able to guess it.
If you want to include or require the PHP directly on another page, just set the POST variable to the password before including it.
$_POST["access"] = "makeupapassword";
require("path/to/the/ajax/file.php");
This is a lot better than maintaining a global variable, session variable, or cookie because some of those are persistent across page loads so you have to make sure to reset the state after checking so users can't get accidental access.
Also I think it is better than page headers because it can't be sniffed since it is secured by HHTPS.
You'll probably have to have some kind of cookie-based authentication. In addition, Ignacio has a good point about using POST. This can help prevent JSON hijacking if you have untrusted scripts running on your domain. However, I don't think using POST is strictly necessary unless the outermost JSON type is an array. In your example it is an object.