diff --git a/README.md b/README.md index efa17fb..0530dc4 100644 --- a/README.md +++ b/README.md @@ -4,26 +4,47 @@ ## Anpassung der Useranmeldung -#### Registrierung ohne Captcha und E-Mail-Verifikation +#### Registrierung mit Google reCAPTCHA v3 **Beschreibung:** -Die Registrierung wurde so angepasst, dass Benutzer ohne Captcha und E-Mail-Verifikation registriert werden können. Benutzer werden nach der Registrierung automatisch aktiviert. +Die Registrierung wurde mit Google reCAPTCHA v3 abgesichert. reCAPTCHA v3 arbeitet unsichtbar im Hintergrund und analysiert das Benutzerverhalten, um Bots zu erkennen. E-Mail-Verifizierung ist deaktiviert - Benutzer werden nach der Registrierung automatisch aktiviert. **Technische Umsetzung:** -- Entfernung des Captcha-Features aus dem Registrierungsprozess -- Deaktivierung der E-Mail-Verifizierung -- Automatische Aktivierung neuer Benutzerkonten -- Vereinfachung des Registrierungsformulars +- Integration von Google reCAPTCHA v3 (unsichtbar, keine Checkbox) +- Score-basierte Validierung (0.0 = Bot, 1.0 = Mensch) +- Blockierung bei Score unter 0.5 +- Konfiguration über `RECAPTCHA_SITE_KEY` und `RECAPTCHA_SECRET_KEY` -**Admin-Funktion:** -- Nur Administratoren können über das gleiche Formular neue Benutzer anlegen -- Sicherstellung, dass nur autorisierte Personen Benutzerkonten erstellen können +**Code-Beispiel (View):** +```html + + +``` + +**Code-Beispiel (Server-Validierung):** +```php +$response = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $recaptcha_response); +$response_data = json_decode($response); +if (!$response_data->success || $response_data->score < 0.5) { + // Bot erkannt oder Validierung fehlgeschlagen +} +``` + +**Vorteile von v3:** +- Keine Benutzerinteraktion erforderlich +- Bessere User Experience +- Intelligente Bot-Erkennung durch Verhaltensanalyse ``` -[📸 Screenshot: Vereinfachtes Registrierungsformular] -[📸 Screenshot: Admin-Benutzererstellung] -[📸 Screenshot: Automatisch aktivierter Benutzer] +[📸 Screenshot: Registrierungsformular] +[📸 Screenshot: reCAPTCHA Badge] ``` --- diff --git a/application/config/config.development.php b/application/config/config.development.php index fd599b1..e667dde 100644 --- a/application/config/config.development.php +++ b/application/config/config.development.php @@ -70,12 +70,10 @@ return array( 'DB_PORT' => '3306', 'DB_CHARSET' => 'utf8', /** - * Configuration for: Captcha size - * The currently used Captcha generator (https://github.com/Gregwar/Captcha) also runs without giving a size, - * so feel free to use ->build(); inside CaptchaModel. + * Configuration for: Google reCAPTCHA v2 */ - 'CAPTCHA_WIDTH' => 359, - 'CAPTCHA_HEIGHT' => 100, + 'RECAPTCHA_SITE_KEY' => 'recaptcha-site-key', + 'RECAPTCHA_SECRET_KEY' => 'recaptcha-secret-key', /** * Configuration for: Cookies * 1209600 seconds = 2 weeks diff --git a/application/controller/RegisterController.php b/application/controller/RegisterController.php index dae738b..6a841fc 100644 --- a/application/controller/RegisterController.php +++ b/application/controller/RegisterController.php @@ -22,23 +22,25 @@ class RegisterController extends Controller */ public function index() { - // only admins can access registration; reuse existing admin auth check - Auth::checkAdminAuthentication(); + if (Session::userIsLoggedIn()) { + Redirect::to('index'); + return; + } $this->View->render('register/index'); } - /** - * Register page action - * POST-request after form submit - */ public function register_action() { - // enforce admin-only for registration - Auth::checkAdminAuthentication(); + if (Session::userIsLoggedIn()) { + Redirect::to('index'); + return; + } - RegistrationModel::registerNewUser(); - - Redirect::to('admin/index'); + if (RegistrationModel::registerNewUser()) { + Redirect::to('login'); + } else { + Redirect::to('register'); + } } /** diff --git a/application/model/RegistrationModel.php b/application/model/RegistrationModel.php index d5d2b63..372cc25 100644 --- a/application/model/RegistrationModel.php +++ b/application/model/RegistrationModel.php @@ -15,15 +15,13 @@ class RegistrationModel */ public static function registerNewUser($isAdmin = false) { - // clean the input $user_name = strip_tags(Request::post('user_name')); $user_email = strip_tags(Request::post('user_email')); - // Use 'user_password' if provided (admin registration), otherwise 'user_password_new' - $user_password_new = $isAdmin ? Request::post('user_password_new') : Request::post('user_password_new'); - $user_password_repeat = $user_password_new; // no repeat field + $user_password_new = Request::post('user_password_new'); + $user_password_repeat = $user_password_new; - // validate using existing validators and messages $valid = true; + if (!self::validateRecaptcha()) { $valid = false; } if (!self::validateUserName($user_name)) { $valid = false; } if (!self::validateUserEmail($user_email, $user_email)) { $valid = false; } if (!self::validateUserPassword($user_password_new, $user_password_repeat)) { $valid = false; } @@ -77,12 +75,35 @@ class RegistrationModel return $return; } - /** - * Validates the username - * - * @param $user_name - * @return bool - */ + public static function validateRecaptcha() + { + $recaptcha_response = Request::post('g-recaptcha-response'); + + if (empty($recaptcha_response)) { + Session::add('feedback_negative', 'reCAPTCHA verification failed. Please try again.'); + return false; + } + + $secret_key = Config::get('RECAPTCHA_SECRET_KEY'); + $verify_url = 'https://www.google.com/recaptcha/api/siteverify'; + + $response = file_get_contents($verify_url . '?secret=' . $secret_key . '&response=' . $recaptcha_response); + $response_data = json_decode($response); + + if (!$response_data->success) { + Session::add('feedback_negative', 'reCAPTCHA verification failed. Please try again.'); + return false; + } + + // v3 returns a score from 0.0 to 1.0 (1.0 = likely human, 0.0 = likely bot) + if (isset($response_data->score) && $response_data->score < 0.5) { + Session::add('feedback_negative', 'Registration blocked due to suspicious activity.'); + return false; + } + + return true; + } + public static function validateUserName($user_name) { if (empty($user_name)) { @@ -90,7 +111,6 @@ class RegistrationModel return false; } - // if username is too short (2), too long (64) or does not fit the pattern (aZ09) if (!preg_match('/^[a-zA-Z0-9]{2,64}$/', $user_name)) { Session::add('feedback_negative', Text::get('FEEDBACK_USERNAME_DOES_NOT_FIT_PATTERN')); return false; diff --git a/application/view/login/index.php b/application/view/login/index.php index a5bd2b0..8306903 100644 --- a/application/view/login/index.php +++ b/application/view/login/index.php @@ -37,6 +37,9 @@ + diff --git a/application/view/register/index.php b/application/view/register/index.php index 472038a..b76f0aa 100644 --- a/application/view/register/index.php +++ b/application/view/register/index.php @@ -1,18 +1,30 @@ -
+ - +
renderFeedbackMessages(); ?> -
+ +