Recaptcha with scala and play framework - java

by using tutorial , i am trying to apply captcha in my play project.
HTML
<form action="/applyForWork" method="post" enctype="multipart/form-data">
<input type="text" name="relevant" id="relevant" >
<input type="file" name="file"/>
<br/>
#Html(views.ReCaptcha.render())
<br/>
<input type="submit" value="Upload"/>
</form>
Controller
def applyForWork = Action {
implicit request =>
println(request.body.asFormUrlEncoded) //None
Ok("submitted")
}
Q1.why this println(request.body.asFormUrlEncoded) gives None?
Q2.captcha box is shown in my html but how to validate it is correct
or not?
I am using scala 2.10 with play framework 2.2

A1. The reason of this is enctype of your form. When you use multipart/form-data you can access form data with:
request.body.asMultipartFormData
A2. Anyway, if I were you I would stick to the solution presented in the tutorial you mentioned and create form mapping for recaptcha values.
case class CaptchaForm(challenge: String, response: String)
val captchaForm = Form[CaptchaForm](
mapping(
"recaptcha_challenge_field" -> nonEmptyText,
"recaptcha_response_field" -> nonEmptyText
)(CaptchaForm.apply)(CaptchaForm.unapply)
)
This way you can reuse it anywhere you need to handle Repatcha.
def applyForWork = Action { implicit request =>
captchaForm.bindFromRequest.fold(
formWithErrors => BadRequest("Captcha Param Error"),
captchaForm => {
println(captchaForm.challenge)
println(captchaForm.response)
if (check(request.remoteAddress, captchaForm.challenge, captchaForm.response)) {
//Captcha ok
}
}
)
}
def check(remoteAddress: String, challenge: String, response: String): Boolean = {
val reCaptcha = new ReCaptchaImpl()
reCaptcha.setPrivateKey(privateKey())
val reCaptchaResponse = reCaptcha.checkAnswer(remoteAddress, challenge, response)
reCaptchaResponse.isValid()
}
Hint
Consider using routes mapping in your template instead of hard-coded URLs. In this case replace
action="/applyForWork"
with
action="#routes.YourFormController.handleAction()"
If you ever change your mapping to an action in the routes you won't have to change all your templates that use it.

Related

Java httpServletRequest Into Arrays

I have a jsp page that calls a JavaScript function to dynamically create content like this:
<input type="text" name="loadLocation1" id="loadLocation1" class="loadLocation />
<input type="text" name="loadMagnitude1" id="loadMagnitude1" class="loadMagnitude / >
<input type="text" name="loadLocation2" id="loadLocation2" class="loadLocation />
<input type="text" name="loadMagnitude2" id="loadMagnitude2" class="loadMagnitude / >
and so on
My goal is to end up with two separate arraysLists containing:
[loadLocation1, loadLocation2, etc.]
[loadMagnitude1, loadMagnitude2, etc.]
Right now I have a servlet that is separating out the data into two different arrays in a rather stupid way:
if(req.getParameter("loadLocation1" ) != null ) {
beam.appendForceDistance( Double.parseDouble(req.getParameter("loadLocation1" )));
beam.appendForce( Double.parseDouble(req.getParameter("loadMagnitude1" )));
if(req.getParameter("loadLocation2" ) != null ) {
beam.appendForceDistance( Double.parseDouble(req.getParameter("loadLocation2" )));
beam.appendForce( Double.parseDouble(req.getParameter("loadMagnitude2" )));
etc.
Which isn't expandable at all. I've looked at the HttpServletRequest documentation, without much luck. I was able to iterate over a map and get the strings of keys and values to print out which wasn't much help since I couldn't separate results by class name.
Also, the getAttribute() looked promising, but when I called it on a request:
req.getAttribute("loadLocation")
it returns null.
Is there any way to separate the two types of data based on class into two different arrays while maintaining the order?
No, this is not possible.
When the form is submitted only the form elements with the "name" attribute will be submitted.
The order will remain exactly the same so that part is solved.
What I would suggest is to create the Object with javascript and post that with ajax.
// One Load object
function Load(args) {
this.kind = args.kind || null; // Location or Magnitude
this.value = args.value || null;
this.clazz = args.clazz || null;
}
var arr = new Array();
var loads = document.getElementsByName('load');
for (var i=0; i< loads.length; i++) {
arr[i] = new Load({
kind: loads[i].id,
value: loads[i].value.
clazz: loads[i].getAttribute('class').
});
}
Use JQuery to post this:
$.postJSON(getHost() + "save/load",arr, function(data) {
});
And your jsp looks like this
<input type="text" name="load" class="loadLocation />
<input type="text" name="load" class="loadMagnitude / >
<input type="text" name="load" class="loadLocation />
<input type="text" name="load" class="loadMagnitude / >
The code is not tested or perfect but you get the idea I hope.

Google reCAPTCHA: How to get user response and validate in the server side?

I am doing a Java (JSP + Servlet) web application (I understand that this question is technology-independent). I hope to use the latest Google reCAPTCHA service.
I am playing with a Google reCAPTCHA example found here:
https://developers.google.com/recaptcha/docs/display#config
<html>
<head>
<title>reCAPTCHA demo: Simple page</title>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<form action="?" method="POST">
<div class="g-recaptcha" data-sitekey="my_site_key"></div>
<br/>
<input type="submit" value="Submit">
</form>
</body>
</html>
I am able to see the displayed recaptcha image as follows:
When I check "I'm not a robot", I get the following:
As you can see, there is a Verify button and based on my tests, user response is sent to Google for verification.
How can I get the user response so that I can verify user response in my own backend code (as suggested by Google at https://developers.google.com/recaptcha/docs/verify).
g-recaptcha-response POST parameter when the user submits the form on your site
On the server side, I can, by clicking on the "Submit" button, get user input from parameter "g-recaptcha-response" only when a user is verified successfully with Google first. Otherwise, "g-recaptcha-response" is blank on the server side. This means that I can do server-side verification only after the client-side's verification success. If so, what is the point of doing another verification on the server-side, which is the option provided by Google reCAPTHA?
Do I miss anything?
The cool thing about the new Google Recaptcha is that the validation is now completely encapsulated in the widget. That means, that the widget will take care of asking questions, validating responses all the way till it determines that a user is actually a human, only then you get a g-recaptcha-response value.
But that does not keep your site safe from HTTP client request forgery.
Anyone with HTTP POST knowledge could put random data inside of the g-recaptcha-response form field, and fool your site to make it think that this field was provided by the google widget. So you have to validate this token.
In human speech, it would be like,
Your Server: Hey Google, there's a dude that tells me that he's not a robot. He says that you already verified that he's a human, and he told me to give you this token as proof of that.
Google: Hmm... let me check this token... yes I remember this dude I gave him this token... yeah he's made of flesh and bone let him through.
Your Server: Hey Google, there's another dude that tells me that he's a human. He also gave me a token.
Google: Hmm... it's the same token you gave me last time... I'm pretty sure this guy is trying to fool you. Tell him to get off your site.
Validating the response is really easy. Just make a GET request to
https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=response_string&remoteip=user_ip_address
And replace the response_string with the value that you earlier got by the g-recaptcha-response field.
You will get a JSON Response with a success field.
More information here:
https://developers.google.com/recaptcha/docs/verify
Edit: It's actually a POST, as per documentation here.
A method I use in my login servlet to verify reCaptcha responses. Uses classes from the java.json package. Returns the API response in a JsonObject.
Check the success field for true or false
private JsonObject validateCaptcha(String secret, String response, String remoteip)
{
JsonObject jsonObject = null;
URLConnection connection = null;
InputStream is = null;
String charset = java.nio.charset.StandardCharsets.UTF_8.name();
String url = "https://www.google.com/recaptcha/api/siteverify";
try {
String query = String.format("secret=%s&response=%s&remoteip=%s",
URLEncoder.encode(secret, charset),
URLEncoder.encode(response, charset),
URLEncoder.encode(remoteip, charset));
connection = new URL(url + "?" + query).openConnection();
is = connection.getInputStream();
JsonReader rdr = Json.createReader(is);
jsonObject = rdr.readObject();
} catch (IOException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
return jsonObject;
}
Hi curious you can validate your google recaptcha at client side also 100% work for me to verify your google recaptcha just see below code
This code at the html body:
<div class="g-recaptcha" id="rcaptcha" style="margin-left: 90px;" data-sitekey="my_key"></div>
<span id="captcha" style="margin-left:100px;color:red" />
This code put at head section on call get_action(this) method form button:
function get_action(form) {
var v = grecaptcha.getResponse();
if(v.length == 0)
{
document.getElementById('captcha').innerHTML="You can't leave Captcha Code empty";
return false;
}
if(v.length != 0)
{
document.getElementById('captcha').innerHTML="Captcha completed";
return true;
}
}
Here is complete demo code to understand client side and server side process. you can copy paste it and just replace google site key and google secret key.
<?php
if(!empty($_REQUEST))
{
// echo '<pre>'; print_r($_REQUEST); die('END');
$post = [
'secret' => 'Your Secret key',
'response' => $_REQUEST['g-recaptcha-response'],
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://www.google.com/recaptcha/api/siteverify");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close ($ch);
echo '<pre>'; print_r($server_output); die('ss');
}
?>
<html>
<head>
<title>reCAPTCHA demo: Explicit render for multiple widgets</title>
<script type="text/javascript">
var site_key = 'Your Site key';
var verifyCallback = function(response) {
alert(response);
};
var widgetId1;
var widgetId2;
var onloadCallback = function() {
// Renders the HTML element with id 'example1' as a reCAPTCHA widget.
// The id of the reCAPTCHA widget is assigned to 'widgetId1'.
widgetId1 = grecaptcha.render('example1', {
'sitekey' : site_key,
'theme' : 'light'
});
widgetId2 = grecaptcha.render(document.getElementById('example2'), {
'sitekey' : site_key
});
grecaptcha.render('example3', {
'sitekey' : site_key,
'callback' : verifyCallback,
'theme' : 'dark'
});
};
</script>
</head>
<body>
<!-- The g-recaptcha-response string displays in an alert message upon submit. -->
<form action="javascript:alert(grecaptcha.getResponse(widgetId1));">
<div id="example1"></div>
<br>
<input type="submit" value="getResponse">
</form>
<br>
<!-- Resets reCAPTCHA widgetId2 upon submit. -->
<form action="javascript:grecaptcha.reset(widgetId2);">
<div id="example2"></div>
<br>
<input type="submit" value="reset">
</form>
<br>
<!-- POSTs back to the page's URL upon submit with a g-recaptcha-response POST parameter. -->
<form action="?" method="POST">
<div id="example3"></div>
<br>
<input type="submit" value="Submit">
</form>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
async defer>
</script>
</body>
</html>

form auto submits multiple times

I need to send a few hidden variable to the struts controller on auto submit of the form. I am sending the variables just fine but since I have the form submit in the document on ready function. The form re submits infinitely . I need to stop the submit after first time submit . Any suggestions ? Below is what I tried.
Code
<script>
$(document).ready (function () {
document.getElementById ('action').value ='hello';
document.getElementById ('myform').submit ();
})
</script>
<form action="/rlogin" id="myform">
<input type=hidden id=user value=you>
<input type=hidden id=action />
Check weither a variable created after the submit has been created or not.
$(document).ready (function () {
if (typeof mySent == 'undefined') {
document.getElementById ('action').value ='hello';
document.getElementById ('myform').submit ();
mySent = true;
}
}

Get HTML nodes that have the same parent - JAVA

I have a document containing several forms similar to the example posted below. I want to extract all the name/value pairs from the hidden input fields of one of the forms, the form is identified by its name and I don't know in advance how many hidden fields will be present.
I am able to select all the relevant input fields in the document using the selector query: input[type=hidden][name][value]
Is there a way to only select the input fields which has FORM[name=lgo] as parent? Using some kind filter maybe?
<FORM METHOD='POST' onSubmit='javascript:isWaitForm();' ACTION='https://abc-azerty.querty.se/carmon/servlet/action/change_1 ' name='lgo'>
<input type='hidden' name='LogInFlag' value='1'>
<input type='hidden' name='LogInTime' value='2011-07-26 11:10'>
<input type='hidden' name='cCode2' value='SE'>
<a href='javascript:isWaitForm();javascript:document.lgo.submit();' class='linkNone'>Business Monitor</a>
<a href='javascript:isWaitForm();javascript:document.lgo.submit();' class='linkNone'>
<input type='image' src='/images/button_arrow_right.gif' height=19 width=22 border=0 style='float:left;'></A>
</FORM>
Based on this info, at least one of following should work -
doc.select("form[name=lgo] > input[type=hidden]");
Or, you can chain your selects -
doc.select("form[name=lgo]").select("input[type=hidden]");
The select method is available in a Document, Element, or in Elements. It is contextual, so you can filter by selecting from a specific element, or by chaining select calls.
<script type="text/javascript">
var inputs = document.getElementsByName('lgo')[0].getElementsByTagName('input');
for(var i = 0 ; i < inputs.length ; i++){
if(inputs[i].getAttribute('type') == "hidden") {
// This will get the name: inputs[i].getAttribute('name')
// This will get the value: inputs[i].value)
console.log(inputs[i].getAttribute('name') + ": " + inputs[i].value);
}}
</script>

include javascript query parameters in URL?

I am currently working on downloading the data automatically on this page:
http://jcmramp.pjm.com/jcmRamp/ramp-data.jsp
I would like to somehow be able to control the URL so that, say, when I use the URL:
jcmramp.pjm.com/jcmRamp/ramp-data.jsp?directionSlt=1
the option selected for Location parameter would be PJM and when I do
jcmramp.pjm.com/jcmRamp/ramp-data.jsp?directionSlt=2
the option selected for Location parameter would be MISO
Here is the relevant section in the HTML code I can see:
<td colspan="4" align="top">
<label id="selectLbl" for="directionSlt" unselectable="on">Location:</label>
<select name="directionSlt" id="directionSlt" size="1" onchange="refresh()">
<option value="1">PJM
<option value="2">MISO
</select>
<label class="linkLabel" id="helpLbl" onmouseover="this.style.color='orange'" onmouseout="this.style.color='navy'" onclick="javascript:openHelpPage();"> - README (ramp viewer description document)</label>
<br><br>
</td>
However, this does not seem to work, no matter what I put for directionSlt, I get PJM, which is the default selection.
I am just wondering if there is any other way possible to manipulate the URL to change the option.
If not, is it possible for me to programatically (using VB.Net) to switch between different option?
(Note: the HTTP sign for the second and third URLs are removed as per website's restrictions)
try this:
(function ($) {
$.locationSearch = function () {
var resultado = [];
try {
var search = window.location.search;
if (search == null || search == '')
return [];
search = search.replace(/\?/, '').split('&');
for (var i in search)
resultado[search[i].split('=')[0]] = search[i].split('=')[1];
}
catch (ex) {}
return resultado;
};
})(jQuery);
$(function() {
var query = $.locationSearch();
if (typeof query['directionSlt'] != 'undefined') {
$('#directionSlt').val(query['directionSlt']);
}
});

Categories