Recaptcha support

Added configuration options to allow reCAPTCHA to be integrated into the registration process. reCAPTCHA response is validated on sign-up if enabled.
This commit is contained in:
Andy Heathershaw 2016-09-08 11:02:49 +01:00
parent 1a08ef1828
commit 821bfceb09
9 changed files with 125 additions and 15 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@
Homestead.json
Homestead.yaml
.env
composer.phar

View File

@ -59,6 +59,9 @@ class ConfigHelper
'date_format' => $this->allowedDateFormats()[0],
'items_per_page' => 12,
'items_per_page_admin' => 10,
'recaptcha_enabled_registration' => false,
'recaptcha_secret_key' => '',
'recaptcha_site_key' => '',
'require_email_verification' => true,
'sender_address' => sprintf('hostmaster@%s', (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost')),
'sender_name' => (is_null($currentAppName) ? trans('global.app_name') : $currentAppName),

View File

@ -0,0 +1,36 @@
<?php
namespace App\Helpers;
use App\Facade\UserConfig;
class RecaptchaHelper
{
/**
* Validates the given reCAPTCHA response against the reCAPTCHA servers to see if the user was validated successfully.
* @param string $response Response from the g-recaptcha-response POST variable
* @param string $clientIpAddress Client's IP address
* @return mixed Returns true or false depending on the reCAPTCHA server's response
* @throws \Exception Thrown when the reCAPTCHA server could not be reached, or it didn't return a valid JSON response.
*/
public static function validateResponse($response, $clientIpAddress)
{
$ch = curl_init(config('services.recaptcha.verify_url'));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'secret' => UserConfig::get('recaptcha_secret_key'),
'response' => $response,
'remoteip' => $clientIpAddress
));
$return = json_decode(curl_exec($ch));
if (is_null($return))
{
throw new \Exception('Error while communicating with the reCAPTCHA service.');
}
return $return->success;
}
}

View File

@ -40,7 +40,8 @@ class DefaultController extends Controller
$checkboxKeys = [
'allow_self_registration',
'require_email_verification',
'smtp_encryption'
'smtp_encryption',
'recaptcha_enabled_registration'
];
$updateKeys = [
'app_name',
@ -51,7 +52,9 @@ class DefaultController extends Controller
'smtp_port',
'smtp_username',
'smtp_password',
'theme'
'theme',
'recaptcha_site_key',
'recaptcha_secret_key'
];
$defaults = UserConfig::defaults();

View File

@ -5,6 +5,7 @@ namespace App\Http\Controllers\Auth;
use App\Facade\Theme;
use App\Facade\UserConfig;
use App\Helpers\MiscHelper;
use App\Helpers\RecaptchaHelper;
use App\Mail\UserActivationRequired;
use App\User;
use Illuminate\Http\Request;
@ -51,13 +52,27 @@ class RegisterController extends Controller
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
protected function validator(Request $request)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
return Validator::make(
$request->all(),
[
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]
)
->after(function($validator) use ($request)
{
// reCAPTCHA validation
if (
UserConfig::get('recaptcha_enabled_registration') &&
!RecaptchaHelper::validateResponse($request->request->get('g-recaptcha-response'), $request->getClientIp())
)
{
$validator->errors()->add('recaptcha', trans('auth.recaptcha_failed_message'));
}
});
}
/**
@ -96,7 +111,7 @@ class RegisterController extends Controller
return redirect(route('home'));
}
$this->validator($request->all())->validate();
$this->validator($request)->validate();
/** @var User $user */
$user = $this->create($request->all());

View File

@ -14,7 +14,11 @@ return [
|
*/
'mailgun' => [
'recaptcha' => [
'verify_url' => 'https://www.google.com/recaptcha/api/siteverify'
]
/*'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
],
@ -33,6 +37,6 @@ return [
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
],*/
];

View File

@ -23,5 +23,6 @@ return [
'forgot_password_link' => 'Forgotten your password?',
'forgot_password_title' => 'Send password reset link',
'login_page_title' => 'Login',
'recaptcha_failed_message' => 'The reCAPTCHA verfication failed. Please ensure you have completed the reCAPTCHA challenge and try again.',
'register_page_title' => 'Create an account'
];

View File

@ -84,7 +84,7 @@
<div class="checkbox">
<label>
<input type="checkbox" name="smtp_encryption" @if (UserConfig::get('smtp_encryption') == 1)checked="checked"@endif>
<input type="checkbox" name="smtp_encryption" @if (UserConfig::get('smtp_encryption'))checked="checked"@endif>
<strong>Requires encrypted connection</strong>
</label>
</div>
@ -105,10 +105,10 @@
</div>
{{-- Security --}}
<div role="tabpanel" class="tab-pane" id="security-tab">
<fieldset role="tabpanel" class="tab-pane" id="security-tab">
<div class="checkbox">
<label>
<input type="checkbox" name="allow_self_registration" @if (UserConfig::get('allow_self_registration') == 1)checked="checked"@endif>
<input type="checkbox" name="allow_self_registration" @if (UserConfig::get('allow_self_registration'))checked="checked"@endif>
<strong>Allow self-registration</strong><br/>
With this option enabled, users can sign up for their own &quot;visitor&quot; accounts to comment on photos.
</label>
@ -116,15 +116,38 @@
<div class="checkbox" style="margin-top: 20px;">
<label>
<input type="checkbox" name="require_email_verification" @if (UserConfig::get('require_email_verification') == 1)checked="checked"@endif>
<input type="checkbox" name="require_email_verification" @if (UserConfig::get('require_email_verification'))checked="checked"@endif>
<strong>Require e-mail verification for self-registered accounts</strong><br/>
<span class="text-danger">It is strongly recommended to enable this option.</span>
</label>
</div>
<div class="checkbox" style="margin-top: 20px;">
<label>
<input type="checkbox" name="recaptcha_enabled_registration" @if (UserConfig::get('recaptcha_enabled_registration'))checked="checked"@endif>
<strong>Enable <a href="https://www.google.com/recaptcha" target="_blank">reCAPTCHA</a> for self-registrations</strong><br/>
<span class="text-danger">It is strongly recommended to enable this option.</span>
</label>
</div>
<fieldset style="margin-top: 30px;">
<legend>reCAPTCHA settings</legend>
<div class="form-group">
{!! Form::label('recaptcha_site_key', 'Site key:', ['class' => 'control-label']) !!}
{!! Form::text('recaptcha_site_key', old('recaptcha_site_key'), ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('recaptcha_secret_key', 'Secret key:', ['class' => 'control-label']) !!}
{!! Form::text('recaptcha_secret_key', old('recaptcha_secret_key'), ['class' => 'form-control']) !!}
</div>
</fieldset>
</div>
</div>
</div>
<div class="clearfix"><!-- --></div>
<div class="text-right" style="margin-top: 15px;">
<a href="{{ route('admin') }}" class="btn btn-default">@lang('forms.cancel_action')</a>
{!! Form::submit(trans('admin.settings_save_action'), ['class' => 'btn btn-success']) !!}

View File

@ -67,8 +67,26 @@
</div>
</div>
@if (UserConfig::get('recaptcha_enabled_registration'))
<div class="form-group">
@if ($errors->has('recaptcha'))
<div class="col-md-12">
<div class="alert alert-danger">
<i class="fa fa-fw fa-warning"></i>
{{ $errors->first('recaptcha') }}
</div>
</div>
@endif
<div class="col-md-6 col-md-offset-4">
<div class="g-recaptcha" data-sitekey="{{ UserConfig::get('recaptcha_site_key') }}"></div>
</div>
</div>
@endif
<div class="form-group">
<div class="col-md-6 col-md-offset-4 text-right">
<a href="{{ route('home') }}" class="btn btn-default">@lang('forms.cancel_action')</a>
<button type="submit" class="btn btn-success">@lang('forms.register_action')</button>
</div>
</div>
@ -79,3 +97,9 @@
</div>
</div>
@endsection
@if (UserConfig::get('recaptcha_enabled_registration'))
@push('scripts')
<script src="https://www.google.com/recaptcha/api.js"></script>
@endpush
@endif