Hashování hesla, generování náhodného tokenu, částečný převod chyb na uživatelsky přijatelné hlášky.
1.1 --- a/java/nekurak.net-ejb/src/java/cz/frantovo/nekurak/ejb/UzivatelEJB.java Thu Mar 04 12:02:41 2010 +0100
1.2 +++ b/java/nekurak.net-ejb/src/java/cz/frantovo/nekurak/ejb/UzivatelEJB.java Thu Mar 04 14:09:21 2010 +0100
1.3 @@ -2,6 +2,11 @@
1.4
1.5 import cz.frantovo.nekurak.dao.UzivatelDAO;
1.6 import cz.frantovo.nekurak.dto.Uzivatel;
1.7 +import cz.frantovo.nekurak.util.Hash;
1.8 +import cz.frantovo.nekurak.vyjimky.NecekanaVyjimka;
1.9 +import cz.frantovo.nekurak.vyjimky.NekurakVyjimka;
1.10 +import java.io.UnsupportedEncodingException;
1.11 +import java.security.NoSuchAlgorithmException;
1.12 import javax.ejb.EJB;
1.13 import javax.ejb.Stateless;
1.14
1.15 @@ -16,7 +21,17 @@
1.16 private UzivatelDAO uzivatelDao;
1.17
1.18 /** Uživatele může zakládat kdokoli – uživatel se registruje sám. */
1.19 - public void zalozUzivatele(Uzivatel u) {
1.20 - uzivatelDao.uloz(u);
1.21 + public void zalozUzivatele(Uzivatel u) throws NekurakVyjimka {
1.22 + try {
1.23 + /** Heslo musíme před uložení zahashovat, aby se uživatel mohl přihlásit. */
1.24 + u.setHeslo(Hash.hashuj(u.getHeslo()));
1.25 + uzivatelDao.uloz(u);
1.26 + } catch (NoSuchAlgorithmException e) {
1.27 + /** Nemělo by nastat */
1.28 + throw new NecekanaVyjimka("Neexistující hashovací algoritmus.", e);
1.29 + } catch (UnsupportedEncodingException e) {
1.30 + /** Nemělo by nastat */
1.31 + throw new NecekanaVyjimka("Nepodporované kódování znaků.", e);
1.32 + }
1.33 }
1.34 }
2.1 --- a/java/nekurak.net-lib/src/cz/frantovo/nekurak/ejb/UzivatelRemote.java Thu Mar 04 12:02:41 2010 +0100
2.2 +++ b/java/nekurak.net-lib/src/cz/frantovo/nekurak/ejb/UzivatelRemote.java Thu Mar 04 14:09:21 2010 +0100
2.3 @@ -1,6 +1,7 @@
2.4 package cz.frantovo.nekurak.ejb;
2.5
2.6 import cz.frantovo.nekurak.dto.Uzivatel;
2.7 +import cz.frantovo.nekurak.vyjimky.NekurakVyjimka;
2.8 import javax.ejb.Remote;
2.9
2.10 /**
2.11 @@ -10,6 +11,5 @@
2.12 @Remote
2.13 public interface UzivatelRemote {
2.14
2.15 - public void zalozUzivatele(Uzivatel u);
2.16 -
2.17 + public void zalozUzivatele(Uzivatel u) throws NekurakVyjimka;
2.18 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/java/nekurak.net-lib/src/cz/frantovo/nekurak/util/Hash.java Thu Mar 04 14:09:21 2010 +0100
3.3 @@ -0,0 +1,47 @@
3.4 +package cz.frantovo.nekurak.util;
3.5 +
3.6 +import java.io.UnsupportedEncodingException;
3.7 +import java.security.MessageDigest;
3.8 +import java.security.NoSuchAlgorithmException;
3.9 +
3.10 +/**
3.11 + * Pomocná třída pro počítání hashů.
3.12 + * @author fiki
3.13 + */
3.14 +public class Hash {
3.15 +
3.16 + private static String algoritmus = "SHA-1";
3.17 + private static String kodovani = "UTF-8";
3.18 +
3.19 + private static String prevedNaHex(byte[] data) {
3.20 + StringBuffer vysledek = new StringBuffer();
3.21 + for (int i = 0; i < data.length; i++) {
3.22 + int pulBajt = (data[i] >>> 4) & 0x0F;
3.23 + int dvePulky = 0;
3.24 + do {
3.25 + if ((0 <= pulBajt) && (pulBajt <= 9)) {
3.26 + vysledek.append((char) ('0' + pulBajt));
3.27 + } else {
3.28 + vysledek.append((char) ('a' + (pulBajt - 10)));
3.29 + }
3.30 + pulBajt = data[i] & 0x0F;
3.31 + } while (dvePulky++ < 1);
3.32 + }
3.33 + return vysledek.toString();
3.34 + }
3.35 +
3.36 + /**
3.37 + * @param text vstupní text
3.38 + * @return hashovaný text v HEX tvaru
3.39 + * @throws NoSuchAlgorithmException neexistující hashovací algoritmus
3.40 + * @throws UnsupportedEncodingException nepodporované kódování znaků
3.41 + */
3.42 + public static String hashuj(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
3.43 + MessageDigest md;
3.44 + md = MessageDigest.getInstance(algoritmus);
3.45 + byte[] hash = new byte[40];
3.46 + md.update(text.getBytes(kodovani), 0, text.length());
3.47 + hash = md.digest();
3.48 + return prevedNaHex(hash);
3.49 + }
3.50 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/java/nekurak.net-lib/src/cz/frantovo/nekurak/vyjimky/NecekanaVyjimka.java Thu Mar 04 14:09:21 2010 +0100
4.3 @@ -0,0 +1,12 @@
4.4 +package cz.frantovo.nekurak.vyjimky;
4.5 +
4.6 +/**
4.7 + *
4.8 + * @author fiki
4.9 + */
4.10 +public class NecekanaVyjimka extends NekurakVyjimka {
4.11 +
4.12 + public NecekanaVyjimka(String chyba, Exception e) {
4.13 + super(chyba, e);
4.14 + }
4.15 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/java/nekurak.net-lib/src/cz/frantovo/nekurak/vyjimky/NekurakVyjimka.java Thu Mar 04 14:09:21 2010 +0100
5.3 @@ -0,0 +1,12 @@
5.4 +package cz.frantovo.nekurak.vyjimky;
5.5 +
5.6 +/**
5.7 + *
5.8 + * @author fiki
5.9 + */
5.10 +public class NekurakVyjimka extends Exception {
5.11 +
5.12 + public NekurakVyjimka(String chyba, Exception e) {
5.13 + super(chyba, e);
5.14 + }
5.15 +}
6.1 --- a/java/nekurak.net-web/src/java/cz/frantovo/nekurak/preklady_cs.properties Thu Mar 04 12:02:41 2010 +0100
6.2 +++ b/java/nekurak.net-web/src/java/cz/frantovo/nekurak/preklady_cs.properties Thu Mar 04 14:09:21 2010 +0100
6.3 @@ -56,7 +56,9 @@
6.4 registrace.hotovo.prihlasit=p\u0159ihl\u00E1sit
6.5 registrace.tlacitko=Registrovat se
6.6 registrace.potvrdit=Potvrdit registraci
6.7 -registrace.chybnyToken=Relace vypr\u0161ela, registraci nelze dokon\u010Dit. Vypl\u0148te pros\u00EDm formul\u00E1\u0159 znovu.
6.8 +registrace.vyjimka=Nepoda\u0159ilo se zalo\u017Eit u\u017Eivatele. Po\u017Eadovan\u00E1 p\u0159ezd\u00EDvka je pravd\u011Bpodobn\u011B obsazena.
6.9 +registrace.vyjimka.necekana=Omlouv\u00E1me se, b\u011Bhem registrace do\u0161lo k nezn\u00E1m\u00E9 chyb\u011B.
6.10 +registrace.vyjimka.token=Relace vypr\u0161ela, registraci nelze dokon\u010Dit. Vypl\u0148te pros\u00EDm formul\u00E1\u0159 znovu.
6.11
6.12 dto.uzivatel.prezdivka=P\u0159ezd\u00EDvka
6.13 dto.uzivatel.prezdivka.tip=U\u017Eivatelsk\u00E9 jm\u00E9no
7.1 --- a/java/nekurak.net-web/src/java/cz/frantovo/nekurak/web/RegistraceUzivatele.java Thu Mar 04 12:02:41 2010 +0100
7.2 +++ b/java/nekurak.net-web/src/java/cz/frantovo/nekurak/web/RegistraceUzivatele.java Thu Mar 04 14:09:21 2010 +0100
7.3 @@ -1,8 +1,11 @@
7.4 package cz.frantovo.nekurak.web;
7.5
7.6 +import cz.frantovo.nekurak.vyjimky.NekurakVyjimka;
7.7 import java.util.Collections;
7.8 import java.util.HashMap;
7.9 import java.util.Map;
7.10 +import java.util.logging.Level;
7.11 +import java.util.logging.Logger;
7.12
7.13 /**
7.14 *
7.15 @@ -11,6 +14,7 @@
7.16 public class RegistraceUzivatele {
7.17
7.18 private HledacSluzby hledac = new HledacSluzby();
7.19 + private static final Logger log = Logger.getLogger(RegistraceUzivatele.class.getSimpleName());
7.20 private Map<String, UzivatelPredRegistraci> uzivatele = Collections.synchronizedMap(new HashMap<String, UzivatelPredRegistraci>());
7.21 private String token;
7.22
7.23 @@ -22,16 +26,25 @@
7.24 this.token = token;
7.25 }
7.26
7.27 - public boolean getDokonciRegistraci() {
7.28 + /**
7.29 + * @return true, pokud registrace proběhla, jinak vyhazuje výjimku.
7.30 + * @throws NekurakVyjimka špatný token nebo chyba při zakládání uživatele
7.31 + */
7.32 + public String getDokonciRegistraci() {
7.33
7.34 UzivatelPredRegistraci u = uzivatele.get(token);
7.35
7.36 if (u == null) {
7.37 /** Chybný token – uživatel se snaží dokončit neexistující registraci */
7.38 - return false;
7.39 + return "registrace.vyjimka.token";
7.40 } else {
7.41 - hledac.getUzivatelEJB().zalozUzivatele(u.getUzivatel());
7.42 - return true;
7.43 + try {
7.44 + hledac.getUzivatelEJB().zalozUzivatele(u.getUzivatel());
7.45 + } catch (Exception e) {
7.46 + log.log(Level.WARNING, "Chyba při registraci uživatele.", e);
7.47 + return "registrace.vyjimka";
7.48 + }
7.49 + return null;
7.50 }
7.51 }
7.52 }
8.1 --- a/java/nekurak.net-web/src/java/cz/frantovo/nekurak/web/UzivatelPredRegistraci.java Thu Mar 04 12:02:41 2010 +0100
8.2 +++ b/java/nekurak.net-web/src/java/cz/frantovo/nekurak/web/UzivatelPredRegistraci.java Thu Mar 04 14:09:21 2010 +0100
8.3 @@ -1,6 +1,9 @@
8.4 package cz.frantovo.nekurak.web;
8.5
8.6 import cz.frantovo.nekurak.dto.Uzivatel;
8.7 +import cz.frantovo.nekurak.util.Hash;
8.8 +import java.util.logging.Level;
8.9 +import java.util.logging.Logger;
8.10
8.11 /**
8.12 * Pomocná třída obalujícího uživatele a token (kvůli CSRF)
8.13 @@ -8,6 +11,7 @@
8.14 */
8.15 public class UzivatelPredRegistraci {
8.16
8.17 + private static final Logger log = Logger.getLogger(UzivatelPredRegistraci.class.getSimpleName());
8.18 private Uzivatel uzivatel;
8.19 private final String token = generujToken();
8.20
8.21 @@ -23,9 +27,16 @@
8.22 return token;
8.23 }
8.24
8.25 + /**
8.26 + * @return náhodný token
8.27 + */
8.28 private static String generujToken() {
8.29 - /** TODO: generovat náhodný. */
8.30 - return "XXX_TODO_generovat_nahodny_token";
8.31 + try {
8.32 + return Hash.hashuj(String.valueOf(Math.random()));
8.33 + } catch (Exception e) {
8.34 + log.log(Level.SEVERE, "Chyba při generování háhodného tokenu", e);
8.35 + /** Nemělo by nikdy nastat :-) */
8.36 + return "nbusr123";
8.37 + }
8.38 }
8.39 -
8.40 }
9.1 --- a/java/nekurak.net-web/web/WEB-INF/casti/registrovatUzivatele.jsp Thu Mar 04 12:02:41 2010 +0100
9.2 +++ b/java/nekurak.net-web/web/WEB-INF/casti/registrovatUzivatele.jsp Thu Mar 04 14:09:21 2010 +0100
9.3 @@ -11,8 +11,16 @@
9.4
9.5 <h1><fmt:message key="registrace.nadpis"/></h1>
9.6
9.7 + <!--
9.8 + Registrace probíhá ve třech krocích:
9.9 + 1) uživatel vyplňí formulář
9.10 + 2) zobrazíme mu vyplněné údaje a on si je zkontroluje
9.11 + 3) potvrdí registraci
9.12 + -->
9.13 +
9.14 <c:choose>
9.15 <c:when test="${param.akceRegistrace == 'kontrola'}">
9.16 + <!-- Vypíšeme uživateli údaje, které zadal do formuláře, aby si je mohl zkontrolovat. -->
9.17 <jsp:setProperty name="uzivatel" property="*"/>
9.18 <jsp:setProperty name="uzivatelPredRegistraci" property="uzivatel" value="${uzivatel}"/>
9.19 <jsp:setProperty name="registraceUzivatele" property="uzivatel" value="${uzivatelPredRegistraci}"/>
9.20 @@ -34,11 +42,14 @@
9.21
9.22 </c:when>
9.23 <c:when test="${param.akceRegistrace == 'dokonceni'}">
9.24 -
9.25 + <!-- Uživatel si zkontroloval údaje a chce dokončit svoji registraci. -->
9.26 <jsp:setProperty name="registraceUzivatele" property="token" value="${param.token}"/>
9.27
9.28 + <c:set var="chybaRegistrace" value="${registraceUzivatele.dokonciRegistraci}"/>
9.29 +
9.30 <c:choose>
9.31 - <c:when test="${registraceUzivatele.dokonciRegistraci}">
9.32 + <c:when test="${chybaRegistrace == null}">
9.33 + <!-- Registrace proběhla úspěšně. -->
9.34 <p>
9.35 <fmt:message key="registrace.hotovo"/>&#160;
9.36 <a href="?akce=prihlaseni">
9.37 @@ -47,17 +58,13 @@
9.38 </p>
9.39 </c:when>
9.40 <c:otherwise>
9.41 - <!--
9.42 - Zaznamenali jsme pokus o CSRF nebo vypršela relace
9.43 - a uživatel se pokouší dokončit registraci po dlouhé době.
9.44 - -->
9.45 - <p><fmt:message key="registrace.chybnyToken"/></p>
9.46 + <!-- Během pokusu o registraci uživatele došlo k chybě. -->
9.47 + <p class="chybovaHlaska"><fmt:message key="${chybaRegistrace}"/></p>
9.48 </c:otherwise>
9.49 </c:choose>
9.50 -
9.51 -
9.52 </c:when>
9.53 <c:otherwise>
9.54 + <!-- Zobrazíme uživateli registrační formulář. -->
9.55 <form method="post" action="?akce=registrovatUzivatele&amp;akceRegistrace=kontrola">
9.56 <fieldset>
9.57 <fmt:message key="dto.uzivatel.prezdivka.tip" var="prezdivkaTip"/>
9.58 @@ -74,7 +81,4 @@
9.59 </c:otherwise>
9.60 </c:choose>
9.61
9.62 -
9.63 -
9.64 -
9.65 </jsp:root>