web commit by http://willu.myopenid.com/: Add (buggy) code for todo item
parent
33bfb7bfc7
commit
1020550375
|
@ -13,3 +13,223 @@ I imagine a plugin that modifies the login screen to use <http://recaptcha.net/>
|
|||
>> white/black lists, were you thinking of listing the openids, or the content?
|
||||
>> Something like the moinmoin global <http://master.moinmo.in/BadContent>
|
||||
>> list?
|
||||
|
||||
Okie - I have a first pass of this. There are still some issues.
|
||||
|
||||
Currently the code verifies the CAPTCHA. If you get it right then you're fine.
|
||||
If you get the CAPTCHA wrong then the current code tells formbuilder that
|
||||
one of the fields in invalid. This stops the login from going through.
|
||||
Unfortunately, formbuilder is caching this validity somewhere, and I haven't
|
||||
found a way around that yet. This means that if you get the CAPTCHA
|
||||
wrong, it will continue to fail. You need to load the login page again so
|
||||
it doesn't have the error message on the screen, then it'll work again.
|
||||
|
||||
A second issue is that the OpenID login system resets the 'required' flags
|
||||
of all the other fields, so using OpenID will cause the CAPTCHA to be
|
||||
ignored.
|
||||
|
||||
Instructions
|
||||
=====
|
||||
|
||||
You need to go to <http://recaptcha.net/api/getkey> and get a key set.
|
||||
The keys are added as options.
|
||||
|
||||
reCaptchaPubKey => "LONGPUBLICKEYSTRING",
|
||||
reCaptchaPrivKey => "LONGPRIVATEKEYSTRING",
|
||||
|
||||
You can also use "signInSSL" if you're using ssl for your login screen.
|
||||
|
||||
|
||||
The following code is just inline. It will probably not display correctly, and you should just grab it from the page source.
|
||||
|
||||
----------
|
||||
|
||||
#!/usr/bin/perl
|
||||
# Ikiwiki password authentication.
|
||||
package IkiWiki::Plugin::recaptcha;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use IkiWiki 2.00;
|
||||
|
||||
sub import { #{{{
|
||||
hook(type => "formbuilder_setup", id => "recaptcha", call => \&formbuilder_setup);
|
||||
} # }}}
|
||||
|
||||
sub getopt () { #{{{
|
||||
eval q{use Getopt::Long};
|
||||
error($@) if $@;
|
||||
Getopt::Long::Configure('pass_through');
|
||||
GetOptions("reCaptchaPubKey=s" => \$config{reCaptchaPubKey});
|
||||
GetOptions("reCaptchaPrivKey=s" => \$config{reCaptchaPrivKey});
|
||||
} #}}}
|
||||
|
||||
sub formbuilder_setup (@) { #{{{
|
||||
my %params=@_;
|
||||
|
||||
my $form=$params{form};
|
||||
my $session=$params{session};
|
||||
my $cgi=$params{cgi};
|
||||
my $pubkey=$config{reCaptchaPubKey};
|
||||
my $privkey=$config{reCaptchaPrivKey};
|
||||
debug("Unknown Public Key. To use reCAPTCHA you must get an API key from http://recaptcha.net/api/getkey")
|
||||
unless defined $config{reCaptchaPubKey};
|
||||
debug("Unknown Private Key. To use reCAPTCHA you must get an API key from http://recaptcha.net/api/getkey")
|
||||
unless defined $config{reCaptchaPrivKey};
|
||||
my $tagtextPlain=<<EOTAG;
|
||||
<script type="text/javascript"
|
||||
src="http://api.recaptcha.net/challenge?k=$pubkey">
|
||||
</script>
|
||||
|
||||
<noscript>
|
||||
<iframe src="http://api.recaptcha.net/noscript?k=$pubkey"
|
||||
height="300" width="500" frameborder="0"></iframe><br>
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
||||
<input type="hidden" name="recaptcha_response_field"
|
||||
value="manual_challenge">
|
||||
</noscript>
|
||||
EOTAG
|
||||
|
||||
my $tagtextSSL=<<EOTAGS;
|
||||
<script type="text/javascript"
|
||||
src="https://api-secure.recaptcha.net/challenge?k=$pubkey">
|
||||
</script>
|
||||
|
||||
<noscript>
|
||||
<iframe src="https://api-secure.recaptcha.net/noscript?k=$pubkey"
|
||||
height="300" width="500" frameborder="0"></iframe><br>
|
||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
||||
<input type="hidden" name="recaptcha_response_field"
|
||||
value="manual_challenge">
|
||||
</noscript>
|
||||
EOTAGS
|
||||
|
||||
my $tagtext;
|
||||
|
||||
if ($config{signInSSL}) {
|
||||
$tagtext = $tagtextSSL;
|
||||
} else {
|
||||
$tagtext = $tagtextPlain;
|
||||
}
|
||||
|
||||
if ($form->title eq "signin") {
|
||||
# Give up if module is unavailable to avoid
|
||||
# needing to depend on it.
|
||||
eval q{use LWP::UserAgent};
|
||||
if ($@) {
|
||||
debug("unable to load LWP::UserAgent, not enabling reCaptcha");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("To use reCAPTCHA you must get an API key from http://recaptcha.net/api/getkey")
|
||||
unless $pubkey;
|
||||
debug("To use reCAPTCHA you must get an API key from http://recaptcha.net/api/getkey")
|
||||
unless $privkey;
|
||||
debug("To use reCAPTCHA you must know the remote IP address")
|
||||
unless $session->remote_addr();
|
||||
|
||||
my $extras = $form->keepextras();
|
||||
if ($extras) {
|
||||
push ( @$extras, qw(recaptcha_challenge_field recaptcha_response_field) );
|
||||
} else {
|
||||
$extras = [qw(recaptcha_challenge_field recaptcha_response_field)];
|
||||
}
|
||||
$form->keepextras($extras);
|
||||
|
||||
my $challenge = "invalid";
|
||||
my $response = "invalid";
|
||||
my $result = { is_valid => 0, error => 'recaptcha-not-tested' };
|
||||
|
||||
$form->field(
|
||||
name => "recaptcha",
|
||||
label => "",
|
||||
type => 'static',
|
||||
comment => $tagtext,
|
||||
required => 1,
|
||||
message => "CAPTCHA verification failed",
|
||||
);
|
||||
|
||||
# validate the captcha.
|
||||
if ($form->submitted && $form->submitted eq "Login" &&
|
||||
defined $form->cgi_param("recaptcha_challenge_field") &&
|
||||
length $form->cgi_param("recaptcha_challenge_field") &&
|
||||
defined $form->cgi_param("recaptcha_response_field") &&
|
||||
length $form->cgi_param("recaptcha_response_field")) {
|
||||
|
||||
$form->field(name => "recaptcha",
|
||||
message => "CAPTCHA verification failed",
|
||||
required => 1,
|
||||
validate => sub {
|
||||
if ($challenge ne $form->cgi_param("recaptcha_challenge_field") or
|
||||
$response ne $form->cgi_param("recaptcha_response_field")) {
|
||||
$challenge = $form->cgi_param("recaptcha_challenge_field");
|
||||
$response = $form->cgi_param("recaptcha_response_field");
|
||||
warn("Validating: ".$challenge." ".$response);
|
||||
$result = check_answer($privkey,
|
||||
$session->remote_addr(),
|
||||
$challenge, $response);
|
||||
} else {
|
||||
warn("re-Validating");
|
||||
}
|
||||
if ($result->{is_valid}) {
|
||||
warn("valid");
|
||||
return 1;
|
||||
} else {
|
||||
warn("invalid");
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} # }}}
|
||||
|
||||
# The following function is borrowed with modifications from
|
||||
# Captcha::reCAPTCHA by Andy Armstrong and is under the PERL Artistic License
|
||||
|
||||
sub check_answer {
|
||||
my ( $privkey, $remoteip, $challenge, $response ) = @_;
|
||||
|
||||
die
|
||||
"To use reCAPTCHA you must get an API key from http://recaptcha.net/api/getkey"
|
||||
unless $privkey;
|
||||
|
||||
die "For security reasons, you must pass the remote ip to reCAPTCHA"
|
||||
unless $remoteip;
|
||||
|
||||
if (! ($challenge && $response)) {
|
||||
warn("Challenge or response not set!");
|
||||
return { is_valid => 0, error => 'incorrect-captcha-sol' };
|
||||
}
|
||||
|
||||
my $ua = LWP::UserAgent->new();
|
||||
|
||||
my $resp = $ua->post(
|
||||
'http://api-verify.recaptcha.net/verify',
|
||||
{
|
||||
privatekey => $privkey,
|
||||
remoteip => $remoteip,
|
||||
challenge => $challenge,
|
||||
response => $response
|
||||
}
|
||||
);
|
||||
|
||||
if ( $resp->is_success ) {
|
||||
my ( $answer, $message ) = split( /\n/, $resp->content, 2 );
|
||||
if ( $answer =~ /true/ ) {
|
||||
warn("CAPTCHA valid");
|
||||
return { is_valid => 1 };
|
||||
}
|
||||
else {
|
||||
chomp $message;
|
||||
warn("CAPTCHA failed: ".$message);
|
||||
return { is_valid => 0, error => $message };
|
||||
}
|
||||
}
|
||||
else {
|
||||
warn("Unable to contact reCaptcha verification host!");
|
||||
return { is_valid => 0, error => 'recaptcha-not-reachable' };
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
Loading…
Reference in New Issue