Questions about implement server side and client side validation - java

I'm working with PlayFramework to build a registration user form that works via Ajax (it never refresh the page) and I obviously need to validate it. I'm considering two way to implement client and server side validation.
Send via Ajax the form data to server side validation, that save the
user in the db if the data is valid, or send an error message to the
frontend in case of invalid data. All of this happens via ajax
without refresh the page.
Pro: In this way I don't implement any
client side validation, but I get the same effect.
Contro: I'm not able to show specific
error messages for each type of invalid data (required, min lenght,
email format, ...)
Validate the form with a client side validation (jQuery Validation
plugin), then if it's valid it sends the data to the server side
validation. From the server side, if it's valid it registers the
user, otherwise nothing happens (?). Pro: Very simple way to show
specific error messages Contro: I need to implement 2 times the same
validation logic
These are my considerations, but I don't know if they're right or if there are other better ways. What is the best way in your opinion to do this?
The questions:
With the first way: Is it possible from server validation send specific error messages and show them on frontend, using PlayFramework (without writing from scratch all the validation rules)?
With the second way: To implement both server and side validations I have to first validate the data with client validation then pass to the server? And with disabled javascript on browser: server side validation has to show something? (for example: notable Mediafire doesn't do that, I have to assume that for correct)
Edit:
Here the code I'm using to receive the form data via ajax in json format:
Controller:
JsonNode json = request().body().asJson();
Form<User> userForm = User.form.bind(json);
if(userForm.hasErrors()) {
return badRequest("One or more inputs are invalid");
} else {
// register the user in the db
}
Model (User):
#Required
public String email;
#Required #MinLength(8) #MaxLength(16)
public String password;
public static Form<User> form = Form.form(User.class);
As it is, it returns a generic message for any invalid inputs. What I'm not able to do is: return (with the badRequest) the specific error messages and show them under each inputs of the form.

You don't need to tell somebody that he tried to login with too short username, in this particular case it's enough if you'll just display an error like: Login incorrect. It's generally adviced to DO NOT tell the user what is the exact reason of the login fail - it prevents (a little) against the tries of brute login attempts.
How do you handle your errors depends on you, you can easily return a JSON object containing list of all errors so you can display them where you want.
For other forms (like some registration, messeging, etc) using ready to use frontend validators is good approach, as you can avoid some reduntand requests and it's just works smoother, anyway main validation should be always be done at the backend - just use frontend one as a "interesting addition to your site".
And don't worry about disabled JS - in this case you will not be able to perform even simple AJAX request ;)
Edit
As mentioned above you can just return a JSON object (also with list of errors) and handle it with JavaScript, although there may be many different approaches, there's one of possibilities:
public static Result submit() {
Form<User> userForm = Form.form(User.class).bindFromRequest();
ObjectNode output = Json.newObject();
if (userForm.hasErrors()) {
output.put("status", 400);
output.put("errors", userForm.errorsAsJson());
return badRequest(output);
}
output.put("status", 200);
output.put("msg", "Your account was registered correctly!");
return ok(output);
}

Related

Spring MVC Request method 'GET' not supported

I have found few questions on this topic however it does not necessary answer my question
Basicaly
I am passing some values via url so data can be gathered from database. I can do it via method= RequestMethod.GET however I would like to do it via POST so users doesnt see parameters in URL.
I am not sure i am using the best method, i bet there is something much advance in order to achieve this .
Cotroller class
#RequestMapping(value="/empresa", method= RequestMethod.POST)
public String empresa(Model model, Principal principal, #RequestParam("get_Business_ID") String get_Business_ID){
// get selected business
List<Business> selectedBusiness = businessService.getBusinessByBusinessID(get_Business_ID);
System.out.println("business selected= "+ selectedBusiness.get(0).getBusiness_name());
model.addAttribute("selectedBusiness",selectedBusiness);
//Destaque semanal
List<Business> businessList = businessService.getCurrentBusiness();
model.addAttribute("businessList", businessList);
return "empresa";
}
JSP page link
href="${pageContext.request.contextPath}/empresa?get_Business_ID=${business.business_id}"
error Type Status Report
Message Request method 'GET' not supported
Description The method received in the request-line is known by the
origin server but not supported by the target resource.
maybe RequestMethod.GET only works if i am using a form with post method?
Is there any other way to achieve this?
Thanks in advance
You have annotated your method with POST
#RequestMapping(value="/empresa", method= RequestMethod.POST)
So change this to
#RequestMapping(value="/empresa", method= RequestMethod.GET)
If you want it to be a POST request try form submit instead of href
Still you need href? then try this
Make a link use POST instead of GET
You are facing this issue because browser never sends anything, browser only receives requests and forwards them to your back end logic.
Difference between GET is simple fetching of data without any data from your side and POST is in information that you send with your request ( for example you send data that you need to save specific customer, I need this firstName, lastName, email etc to be saved ). With that being said, you can switch between #GetMapping or #PostMapping depending what you need for your application.
To be more precise between get and post
GET A GET method should be used to retrieve data from the server. Multiple get requests to the same URL should be valid and no data should be changed on the server side.
However, this doesn't mean it is not possible to make a GET request change things server side, but you should try to make sure you are following the standard.
POST A POST method should be used when you need to create, update or delete data on the server side. Making the same POST request multiple times may not be safe and may result in inconsistent data. The content of a POST request is sent in the request body. Hence, you don't see the parameters in your browser, but it is easy to see them if you wanted to (Even using the browser developer tools) so it is no more safe than a GET request.

Why is my request working without requesting a new XSRF token?

Is it enough to request one XSRF token from the server and reuse it over the whole session or should I request for each protect-worthy action like save, edit or delete a new XSRF token first and then perform the actual request?
This question arises because I don't understand why my XSRF protected request is working even though I am not requesting a new one:
public void saveName(Long shopId, Long languageId, String name, OnSuccessCallback<String> success, OnFailureCallback failure) {
Request.<String> doRequest(this.shopService,
asyncCallback -> {
this.shopService.saveName(shopId, languageId, name, asyncCallback);
},
(String result) -> {
// ..
success.onSuccess(result);
}, failure);
}
Here Request#doRequest() will simply perform a request but won't ask for a new XSRF token first. I would have to change it to XsrfRequest#doRequest() which does the same thing basically but will request a XSRF token first.
The thing is that saveName() is supposed to be protected:
#XsrfProtect
#RemoteServiceRelativePath("shop")
public interface ShopServlet extends RemoteService {
// ..
String saveName(Long shopId, Long languageId, String name);
}
Please note: Before saveName() is getting called there are several other requests of which some of them already get XSRF tokens. But since I can save a new name without requesting a new one I have the feeling that the previous requested token is getting reused here. Is this okay that way?
Another thing I noticed is if I add #NoXsrfProtect to saveName()
#NoXsrfProtect
String saveName(Long restaurantId, Long languageId, String name);
that the request will still contain XSRF token information:
7|2|9|http://localhost:8080/app/|424F33664CAA93E2F8A4A94C57DA5827|com.google.gwt.user.client.rpc.XsrfToken/4254043109|..ShopServlet|saveName|java.lang..
Why is the token being sent here even though the method is declared as #NoXsrfProtect?
Could somebody clarify this to me? I don't want to make any mistakes - especially in security related matters..
Is it enough to request one XSRF token from the server and reuse it over the whole session or should I request for each protect-worthy action like save, edit or delete a new XSRF token first and then perform the actual request?
Lets ignore GWT RPC's built-in XSRF protection for a moment and look at the title question and this remark: What is XSRF and how do we protect against it?
What is XSRF
XSRF stands for Cross Site Request Forgery - the idea is that a malicious site could somehow forge a request, and force one of our users to correctly send it to our application, as if they had intended to do it themselves. For example, if all it took to transfer money from one bank account to another was
GET /transfer?from=me&to=attacker&amount=10000USD
then an attacker could very simply make a request to our server as an image, css, or js file, from their own site:
<img src="https://securebank.com/transfer?from=me&to=attacker&amount=10000USD" />
Setting aside other details ("okay, that works for a GET, how did they manage to send a POST to my GWT RPC service?"), lets look at the idea of a XSRF "token" preventing this attack: what is it that a friendly client knows or can do, that an attacker cannot know or do?
Mitigation
The idea is that the client should have a way to indicate to the server that it is trusted - that it knows something which only a valid client could know, which indicates that the user is willing to make the specified action. One option is to require the user to perform a captcha, in such a way that the action cannot be scripted by the attacking site, and the user must consciously perform. Another option is to make some data available to a real/trusted client, such as cookies (that can only be read from a page loaded on the same domain), or as part of the HTML page as it loads or some other request (which might be possible to be sent by some other means, but the results can't be read).
OWASP refers to this latter piece of data as a "Synchronizer Token":
The synchronizer token pattern requires the generating of random "challenge" tokens that are associated with the user's current session. [...] When the user wishes to invoke these sensitive operations, the HTTP request should include this challenge token. It is then the responsibility of the server application to verify the existence and correctness of this token.
So, in this case, we could write some value to a cookie so that only the client can see it, and the client can then use this to generate a token. That token then should be passed to the server on each request that must be verified. But from this description, we see that it isn't necessarily important to only have one valid token at a time.
But if the attacker can get an XSS, they can just read the token and force the request again! Or MitM!
That's true, but if they have an XSS, then any request that your own JS can make, the attack can make as well. You've lost, pack up shop, time to go home. Likewise if they own the connection between the user and application and can read and write at will. XSRF protection isn't a magic wand that solves all problems, its a specific attack, and only needs to be addressed on its own: a lock in your home isn't considered faulty if the window can be broken.
Okay, back to GWT
So how does GWT do this? As you've noted, the #XsrfProtect annotation marks a service type as needing to be checked on the server. The client then must request a token, and then make sure the client's service is aware of that token for future requests.
So how does the server generate a token? The XsrfTokenServiceServlet RPC service on the server generates the token, as part of each call to the server, as you've observed, XsrfProtectedServiceServlet.validateXsrfToken then verifies that this is correct. If you wanted custom behavior, you'd have to modify each side of that system, and you could build it to invalidate each token once it is used, but this is not the default (nor, according to OWASP, is it encouraged).
Another thing I noticed is if I add #NoXsrfProtect to saveName()...
Note that validateXsrfToken is only called in one place in GWT, from in AbstractXsrfProtectedServiceServlet:
#Override
protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
if (shouldValidateXsrfToken(rpcRequest.getMethod())) {
validateXsrfToken(rpcRequest.getRpcToken(), rpcRequest.getMethod());
}
}
The method shouldValidateXsrfToken then checks if the method expressly has the protection disabled. If so, it will return false, and no check will be performed. But when building up the RPCRequest object, RPC.decodeRequest always appends the token, even if that token happens to be null:
RpcToken rpcToken = null;
if (streamReader.hasFlags(AbstractSerializationStream.FLAG_RPC_TOKEN_INCLUDED)) {
// Read the RPC token
rpcToken = (RpcToken) streamReader.deserializeValue(RpcToken.class);
}
So if the client is configured to send the token, it will always be sent, though the server might ignore it.
More reading:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) and https://www.owasp.org/index.php/CSRF_Prevention_Cheat_Sheet
http://www.gwtproject.org/doc/latest/DevGuideSecurityRpcXsrf.html

Handle request from external website

I'm writing an application that sends requests to the Twitter API. One part of the flow requires a redirect to the Twitter login page. After the user has logged in, a request is sent back to the callback url with information I need to continue the flow. The thing is, after logging in, my application pops up with the relevant information in the url bar. So, for example the url would look like this:
{http://localhost:9000/?oauth_token=KlQrT7YoFC2j3wAVGK57JRRI5h6LFI08H1zkhm8uEo&oauth_verifier=dU1H8D1no1wmKNRdpecHDrWegTQm4dvI15rnUblqxM}
I need the information after the {'http://localhost:9000'} so my question is, how do I get that?
The only information I can find on HTTP Request is making them, very little about receiving them. And even the stuff I did find on receiving them doesn't cover the issue I'm having. I imagine a solution to this problem could be very useful seeing as it goes to the core of any application that wants to implement sign in with Twitter.
Any help would be greatly appreciated.
Create a controller which serves /, example routes file
GET / Twitter.authorize
And then in the controller you can use the parameters:
public static void authorize(String oauth_token, String oauth_verifier) {
.... do something ....
}

Options for passing data across HTTP redirects

I am working on a Web application and need to pass data across HTTP redirects. For example:
http://foo.com/form.html
POSTs to
http://foo.com/form/submit.html
If there is an issue with the data, the Response is redirected back to
http://foo.com/form.html?error=Some+error+message
and the query param "error"'s value is displayed on the page.
Is there any other reliable way to pass data across redirects (ie HTTP headers, etc.).
Passing the data as query params works but isn't ideal because:
its cleartext (and in the query string, so SSL cant be relied on to encyrpt) so I wouldn't want to pass sensitive data
URIs are limited in length by the browser (albiet the length is generally fairly long).
IMPORTANT: This platform is state-less and distributed across many app servers, so I can't track the data in a server-side session object.
From the client-server interaction point of view, this is a server internal dispatch issue.
Browsers are not meant to re-post the entity of the initial request automatically according to the HTTP specification: "The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD."
If it's not already the case, make form.html dynamic so that it's an HTML static file. Send the POST request to itself and pre-fill the value in case of error. Alternatively, you could make submit.html use the same template as form.html if there is a problem.
its cleartext (and in the query string, so SSL cant be relied on to
encyrpt) so I wouldn't want to pass sensitive data
I'm not sure what the issue is here. You're submitting everything over plain HTTP anyway. Cookie, query parameters and request entity will all be visible. Using HTTPS would actually protect all this, although query parameters can still be an issue with browser history and server logs (that's not part of the connection, which is what TLS protects).
I think using cookies would be a reasonable solution depending on the amount of data. As you can't track it on the server side (by using a sessions for example, which would be much simpler)
You can store error message in database on server and reference to it by id:
http://foo.com/form.html?error_id=42
If error texts are fixed you even don't need to use a database.
Also, you can use Web Storage. Instead of redirection with "Location" header you can display output page with this JavaScript:
var error_message = "Something is wrong";
if( typeof(Storage) !== "undefined" ) {
localStorage.error_message = error_message;
else {
// fallback for IE < 8
alert(error_message);
}
location.href = "new url";
And after redirection you can read localStorage.error_message using JavaScript and display the message.

Easiest way to submit a form to ServletUnit using something like WebRequest in HttpUnit

I would like to programmatically create a form with fields etc, however i have not been able to find a public factory etc to create a WebForm(class). Once this is done i would like to then submit the form and have my servlet do stuff with the form.
One approach i noticed the tests use is to create a PseudoServer which is a simple socket server. The tests then eventually make a request to some url which replies with some arbitrary html which includes a form. The problem with this is i cant register my own custom servlet to do stuff.
Im thus stuck between wanting a form but being unable to create one, if i wish to unit servletunit.
Is there a way to submit forms to a servlet inside servlet unit ?
Is there a way to combine parts of httpunit the form submitting stuff w/ servlet unit ?
Im guessing probably not because it(httpunit) wants to submit a form via socket and servletunit does not use sockets at all.
As per Andrey's suggestion and my past experimenting i have attempted to to call numerous methods on WebRequest to attempt to communicate the stuff that exists in a form being posted to a server.
selectFile() - to pick the file to be uploaded
setHeaderField() to set content type/charset/encoding.
You can use PostMethodWebRequest to send POST request to any HTTP URL:
WebRequest request = new PostMethodWebRequest(serverUrl);
And then just set form parameters directly in the request object:
request.setParameter('name', 'user1');
request.setParameter('password', '123456');

Categories