2 Commits

Author SHA1 Message Date
AliceDarkest b4fbc972f2 Merge: Login case-insensitiv + Passwort-Wiederholfeld
mindflux-ci / build (push) Successful in 27s
2026-06-30 20:04:08 +02:00
AliceDarkest 21c594445f Fix: Login case-insensitiv (Registrierung speichert lowercase, Login war case-sensitiv) + Passwort-Wiederholfeld
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:03:46 +02:00
6 changed files with 52 additions and 10 deletions
@@ -49,7 +49,7 @@ public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService(UserRepository userRepo) {
return username -> {
User user = userRepo.findByUsername(username)
User user = userRepo.findByUsernameIgnoreCase(username)
.orElseThrow(() -> new UsernameNotFoundException("Benutzer nicht gefunden"));
return org.springframework.security.core.userdetails.User
@@ -24,17 +24,24 @@ public class RegisterController {
}
@PostMapping("/register")
public String processRegistration(@ModelAttribute("user") User user, Model model) {
// Benutzername klein schreiben, um Doppelungen zu vermeiden
user.setUsername(user.getUsername().toLowerCase());
public String processRegistration(@ModelAttribute("user") User user,
@RequestParam(value = "confirmPassword", required = false) String confirmPassword) {
// Schreibweise des Benutzernamens beibehalten, nur trimmen
String username = user.getUsername() == null ? "" : user.getUsername().trim();
user.setUsername(username);
// Prüfen, ob Benutzername schon existiert
if (userService.findByUsername(user.getUsername()) != null) {
// Zurück zur kombinierten Login/Signup-Seite mit geöffnetem Signup-Panel
// Passwörter müssen übereinstimmen (Schutz vor Tippfehlern bei der Eingabe)
if (user.getPassword() == null || user.getPassword().isBlank()
|| !user.getPassword().equals(confirmPassword)) {
return "redirect:/?passwordMismatch";
}
// Benutzername schon vergeben? (case-insensitiv, damit "Alice" und "alice" nicht kollidieren)
if (username.isBlank() || userService.findByUsernameIgnoreCase(username) != null) {
return "redirect:/?registerError";
}
// Passwort verschlüsseln
// Passwort verschlüsseln und speichern
user.setPassword(passwordEncoder.encode(user.getPassword()));
user.setRole("USER"); // Standardrolle
userService.save(user);
@@ -9,6 +9,9 @@ public interface UserRepository extends JpaRepository<User, Long> {
// Benutzer anhand des Benutzernamens suchen
Optional<User> findByUsername(String username);
// Case-insensitive Suche: Login und Registrierung sollen unabhängig von Groß-/Kleinschreibung greifen
Optional<User> findByUsernameIgnoreCase(String username);
// Benutzer anhand des Benutzernamens löschen
void deleteByUsername(String username);
}
@@ -4,6 +4,7 @@ import com.example.mindflux.model.User;
public interface UserService {
User findByUsername(String username);
User findByUsernameIgnoreCase(String username);
void save(User user);
void deleteByUsername(String username); // <-- Nur die Methodensignatur, ohne {}
}
@@ -25,6 +25,11 @@ public class UserServiceImpl implements UserService {
return userRepository.findByUsername(username).orElse(null); // <-- Optional aufgelöst
}
@Override
public User findByUsernameIgnoreCase(String username) {
return userRepository.findByUsernameIgnoreCase(username).orElse(null);
}
@Override
public void save(User user) {
userRepository.save(user);
+28 -2
View File
@@ -58,6 +58,7 @@
</div>
<div th:if="${param.registerError}" class="mf-alert err">Benutzername bereits vergeben.</div>
<div th:if="${param.passwordMismatch}" class="mf-alert err">Die Passwörter stimmen nicht überein. Bitte erneut eingeben.</div>
<form th:action="@{/register}" method="post">
<div class="mf-field">
@@ -72,6 +73,11 @@
<label class="mf-label" for="reg-password">Passwort</label>
<input id="reg-password" class="mf-input" type="password" name="password" placeholder="Passwort" required>
</div>
<div class="mf-field">
<label class="mf-label" for="reg-password2">Passwort wiederholen</label>
<input id="reg-password2" class="mf-input" type="password" name="confirmPassword" placeholder="Passwort wiederholen" required>
</div>
<p id="reg-pw-msg" class="mf-alert err" style="display:none">Die Passwörter stimmen nicht überein.</p>
<button class="neon-btn" type="submit"><span class="lock">🚀</span> Account erstellen</button>
</form>
@@ -128,10 +134,30 @@
el.addEventListener('click', function (e) { e.preventDefault(); c.classList.remove('active'); });
});
// Bei Registrierungsfehler direkt das Signup-Panel öffnen
if (new URLSearchParams(window.location.search).has('registerError')) {
// Bei Registrierungs-/Passwortfehler direkt das Signup-Panel öffnen
var qp = new URLSearchParams(window.location.search);
if (qp.has('registerError') || qp.has('passwordMismatch')) {
c.classList.add('active');
}
// Client-seitiger Passwort-Abgleich (sofortiges Feedback; der Server prüft zusätzlich)
var pw = document.getElementById('reg-password');
var pw2 = document.getElementById('reg-password2');
var pwMsg = document.getElementById('reg-pw-msg');
var signupForm = pw2 ? pw2.closest('form') : null;
function pwCheck() {
var mismatch = pw2.value.length > 0 && pw.value !== pw2.value;
if (pwMsg) pwMsg.style.display = mismatch ? 'block' : 'none';
pw2.setCustomValidity(pw.value !== pw2.value ? 'Passwörter stimmen nicht überein' : '');
return !mismatch;
}
if (pw && pw2) {
pw.addEventListener('input', pwCheck);
pw2.addEventListener('input', pwCheck);
if (signupForm) signupForm.addEventListener('submit', function (e) {
if (pw.value !== pw2.value) { e.preventDefault(); pwCheck(); c.classList.add('active'); }
});
}
})();
</script>