2 Commits

3 changed files with 130 additions and 40 deletions

View File

@@ -1,25 +0,0 @@
Temat: Analizator haseł
Założenia:
- Sprawdza ile hasło będzie łamane przy pomocy metody Bruteforce (Andrii Solianyk)
- Sprawdza czy hasło nie wyciekło (Patryk Kania)
- Sprawdza jego złożoność (Hubert Salwa)
- Proponuje zmiany hasła w celu poprawy jego złożoności (Hubert Salwa)
- Statystyki złożoności (Andrii Solianyk)
Skład zespołu:
- Andrii Solianyk
- Patryk Kania
- Hubert Salwa
Weryfikator Siły Hasła (Password Validator) to narzędzie służące do kompleksowej oceny bezpieczeństwa wprowadzonych haseł. Aplikacja natychmiastowo analizuje hasło pod kątem siły, sprawdzając takie kryteria jak długość, różnorodność znaków (duże/małe litery, cyfry, symbole) i brak typowych słów słownikowych. Ponadto, kluczową funkcjonalnością jest weryfikacja, czy hasło nie wyciekło wcześniej w wyniku naruszeń danych. Ostatecznym celem aplikacji jest dostarczenie użytkownikowi natychmiastowej informacji zwrotnej i wskazówek, które pomogą mu stworzyć silne i unikalne zabezpieczenie konta.
Do statystyk:
Wypisywanie dodatkowych informacji na temat statystyk liter w tym haslie.
Raport przygotowany w formie dokumentu, rozbudowane sprawozdanie
- wstęp teoretyczny
- implementacja

View File

@@ -3,7 +3,7 @@ package iz._11a.passmetric;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.*;
@Controller
public class PasswordController {
@@ -15,19 +15,38 @@ public class PasswordController {
@PostMapping(path = "/api/password/strength")
@ResponseBody
public Map<String, String> checkPasswordLive(@RequestParam("password") String password) {
return Map.of("message", analyze(password));
public Map<String, Object> checkPasswordLive(@RequestParam("password") String password) {
Map<String, Object> response = new HashMap<>();
int score = calculateScore(password);
String strengthText = strengthText(score);
List<String> tips = generateTips(password);
response.put("strengthText", strengthText);
response.put("progress", score * 20); // pasek postępu 0100%
response.put("tips", tips);
return response;
}
private String analyze(String password) {
// ------------------------------------------
// Ocena siły hasła
// ------------------------------------------
private int calculateScore(String password) {
int score = 0;
if (password != null) {
if (password.matches(".*[a-z].*")) score++;
if (password.matches(".*[A-Z].*")) score++;
if (password.matches(".*[0-9].*")) score++;
if (password.matches(".*[@$!%*?&#].*")) score++;
if (password.length() >= 8) score++;
}
if (password == null || password.isEmpty()) return 0;
if (password.matches(".*[a-z].*")) score++;
if (password.matches(".*[A-Z].*")) score++;
if (password.matches(".*[0-9].*")) score++;
if (password.matches(".*[@$!%*?&#].*")) score++;
if (password.length() >= 12) score++;
return score;
}
private String strengthText(int score) {
return switch (score) {
case 5 -> "Bardzo silne hasło";
case 4 -> "Silne hasło";
@@ -36,4 +55,31 @@ public class PasswordController {
default -> "Bardzo słabe hasło";
};
}
// ------------------------------------------
// Stopniowe podpowiedzi
// ------------------------------------------
private List<String> generateTips(String password) {
List<String> tips = new ArrayList<>();
if (password == null || password.isEmpty()) {
tips.add("Wpisz hasło, aby rozpocząć analizę.");
return tips;
}
if (!password.matches(".*[A-Z].*"))
tips.add("Dodaj co najmniej jedną dużą litere.");
if (!password.matches(".*[0-9].*"))
tips.add("Dodaj co najmniej jedną cyfre.");
if (!password.matches(".*[@$!%*?&#].*"))
tips.add("Dodaj co najmniej jeden znnak specjalny (np. ! @ # $).");
if (password.length() < 12)
tips.add("Wydłuż hasło do co najmniej 12 znaków.");
if (tips.isEmpty())
tips.add("Świetnie! Twoje hasło jest bardzo silne.");
return tips;
}
}

View File

@@ -5,6 +5,32 @@
<title>PassMetric</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" th:href="@{/css/password.css}">
<style>
/* Pasek siły hasła dopasowany do Twojego stylu */
#strengthBarContainer {
width: min(92vw, 480px);
margin: 10px auto 0;
height: 10px;
background: #e2e8f0;
border-radius: 8px;
overflow: hidden;
}
#strengthBarFill {
height: 100%;
width: 0%;
background: var(--bad);
transition: width 200ms ease, background-color 200ms ease;
}
ul#tipsList {
width: min(92vw, 480px);
margin: 10px auto 0;
padding-left: 20px;
font-size: 14px;
color: var(--text);
}
</style>
</head>
<body>
<h1>Sprawdź siłę hasła</h1>
@@ -14,17 +40,35 @@
<input type="password" id="password" autocomplete="off">
</form>
<!-- Pasek siły hasła -->
<div id="strengthBarContainer">
<div id="strengthBarFill"></div>
</div>
<!-- Główny komunikat (słabe, średnie, silne itd.) -->
<p id="liveMessage" aria-live="polite"></p>
<!-- Podpowiedzi krok po kroku -->
<ul id="tipsList"></ul>
<script>
const input = document.getElementById('password');
const out = document.getElementById('liveMessage');
const bar = document.getElementById('strengthBarFill');
const tipsList = document.getElementById('tipsList');
let t;
input.addEventListener('input', () => {
clearTimeout(t);
const val = input.value;
if (!val) { out.textContent = ''; return; }
if (!val) {
out.textContent = '';
out.className = '';
bar.style.width = "0%";
tipsList.innerHTML = '';
return;
}
t = setTimeout(async () => {
try {
@@ -33,27 +77,52 @@
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({ password: val })
});
if (!resp.ok) { out.textContent = 'Błąd sprawdzania'; return; }
if (!resp.ok) {
out.textContent = 'Błąd sprawdzania';
return;
}
const data = await resp.json();
out.textContent = data.message || '';
// Ustawiamy tekst siły hasła
out.textContent = data.strengthText || '';
out.className = '';
switch (data.message) {
switch (data.strengthText) {
case "Bardzo słabe hasło":
out.classList.add("bad");
bar.style.background = "var(--bad)";
break;
case "Słabe hasło":
out.classList.add("warn");
bar.style.background = "var(--warn)";
break;
case "Średnie hasło":
out.classList.add("warn");
bar.style.background = "var(--warn)";
break;
case "Silne hasło":
out.classList.add("ok");
bar.style.background = "var(--ok)";
break;
case "Bardzo silne hasło":
out.classList.add("ok");
bar.style.background = "var(--ok)";
break;
}
// Pasek postępu (0100%)
bar.style.width = (data.progress || 0) + "%";
// Podpowiedzi
tipsList.innerHTML = "";
(data.tips || []).forEach(tip => {
const li = document.createElement("li");
li.textContent = tip;
tipsList.appendChild(li);
});
} catch {
out.textContent = 'Błąd sieci';
}