diff -r aff44e80f418 -r 46bb283a674d java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java
--- a/java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java Tue Feb 07 00:27:39 2012 +0100
+++ b/java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java Tue Feb 07 18:03:31 2012 +0100
@@ -1,8 +1,6 @@
package cz.frantovo.jaas.sql;
-import com.sun.appserv.security.AppservRealm;
import com.sun.enterprise.security.auth.realm.BadRealmException;
-import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
import com.sun.enterprise.security.auth.realm.NoSuchUserException;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -13,7 +11,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
-import java.util.Properties;
import java.util.logging.Level;
import javax.naming.InitialContext;
import javax.naming.NamingException;
@@ -25,52 +22,113 @@
*
* @author fiki
*/
-public class SQLRealm extends AppservRealm {
+public class SQLRealm extends ParametrizovanýRealm {
private static final String AUTH_TYPE = "Ověřuje uživatele proti SQL databázi.";
- private static final String PARAM_JNDI = "jndi";
- private static final String PARAM_SQL_HESLO = "sql_heslo";
- private static final String PARAM_SQL_SKUPINY_UŽIVATELE = "sql_skupiny_uzivatele";
- private static final String PARAM_SQL_SKUPINY_VŠECHNY = "sql_skupiny_vsechny";
- private DataSource datovýZdroj;
+ /**
+ *
JNDI jméno datového zdroje – odkazuje na instanci {@linkplain javax.sql.DataSource}
+ *
+ * Příklady:
+ *
+ *
+ * jdbc/mojeAplikace
+ *
+ */
+ public static final String PARAM_JNDI = "jndi";
+ /** Pokud je nastaveno na "true", nebude se při inicializaci testovat spojení s databází */
+ public static final String PARAM_NETESTOVAT_SPOJENÍ = "netestovat_spojeni";
+ /**
+ * SQL dotaz pro kontrolu hesla.
+ *
+ * Má dva parametry:
+ *
+ * - uživatelské jméno
+ * - heslo
+ *
+ *
+ * Vrací:
+ *
+ * - Při úspěšném ověření jednu hodnotu: uživatelské jméno
+ * - Při neexistujícím uživateli nebo špatném hesle: prázdný výsledek (nula řádků)
+ * - Při jiné chybě: vyhazuje výjimku
+ *
+ *
+ * Příklady:
+ *
+ *
+ * SELECT jmeno FROM uzivatel WHERE jmeno = ? AND heslo = ?
+ * SELECT jmeno FROM uzivatel WHERE jmeno = ? AND heslo = sha1(?)
+ * SELECT zkontroluj_heslo(?, ?)
+ *
+ *
+ * (hashovací a jiné funkce musí být samozřejmě podporované databází)
+ */
+ public static final String PARAM_SQL_HESLO = "sql_heslo";
+ /**
+ * SQL dotaz pro zjištění skupin daného uživatele.
+ *
+ * Má jeden parametr: jméno uživatele
+ *
+ * Příklady:
+ *
+ *
+ * SELECT nazev FROM skupina WHERE uzivatel = ?
+ *
+ */
+ public static final String PARAM_SQL_SKUPINY_UŽIVATELE = "sql_skupiny_uzivatele";
+ /**
+ * SQL dotaz pro zjištění všech skupin v dané bezpečnostní doméně.
+ *
+ * Příklady:
+ *
+ *
+ * SELECT nazev FROM skupina
+ *
+ */
+ public static final String PARAM_SQL_SKUPINY_VŠECHNY = "sql_skupiny_vsechny";
+ private String jndiDatovéhoZdroje;
private String sqlHeslo;
private String sqlSkupinyUživatele;
private String sqlSkupinyVšechny;
- /**
- * Načteme a zkontrolujeme parametry
- *
- * @param parametry
- * @throws BadRealmException pokud je v parametrech chyba
- * @throws NoSuchRealmException
- */
@Override
- public void init(Properties parametry) throws BadRealmException, NoSuchRealmException {
- super.init(parametry);
-
- String jaasContext = parametry.getProperty(JAAS_CONTEXT_PARAM, SQLLoginModul.VÝCHOZÍ_JAAS_KONTEXT);
- setProperty(JAAS_CONTEXT_PARAM, jaasContext);
+ protected void parametrizuj() throws BadRealmException {
+ String jaasContext = getProperties().getProperty(JAAS_CONTEXT_PARAM, SQLLoginModul.VÝCHOZÍ_JAAS_KONTEXT);
+ getProperties().setProperty(JAAS_CONTEXT_PARAM, jaasContext);
/** Databázové spojení */
- {
- String jndi = najdiParametr(parametry, PARAM_JNDI, "název datového zdroje");
+ jndiDatovéhoZdroje = najdiParametr(PARAM_JNDI, "název datového zdroje");
+ testSpojení();
+
+ /** SQL dotazy */
+ sqlHeslo = najdiParametr(PARAM_SQL_HESLO, "SQL dotaz pro ověření jména a hesla");
+ sqlSkupinyUživatele = najdiParametr(PARAM_SQL_SKUPINY_UŽIVATELE, "SQL dotaz pro zjištění skupin uživatele");
+ sqlSkupinyVšechny = najdiParametr(PARAM_SQL_SKUPINY_VŠECHNY, "SQL dotaz pro zjištění všech skupin");
+
+ _logger.log(Level.INFO, "SQLRealm úspěšně parametrizován. JaasContext: {0}, počet parametrů: {1}", new Object[]{getJAASContext(), getProperties().size()});
+ }
+
+ private void testSpojení() throws BadRealmException {
+ if (Boolean.valueOf(getProperty(PARAM_NETESTOVAT_SPOJENÍ))) {
+ _logger.log(Level.WARNING, "Netestujeme databázové spojení při inicializaci.");
+ } else {
try {
- InitialContext k = new InitialContext();
- jndi = parametry.getProperty(PARAM_JNDI);
- datovýZdroj = (DataSource) k.lookup(jndi);
+ Connection s = getSpojení();
+ s.close();
} catch (NamingException e) {
- throw new BadRealmException("Datový zdroj s tímto názvem nebyl nalezen: " + jndi, e);
+ throw new BadRealmException("Datový zdroj s tímto názvem nebyl nalezen: " + jndiDatovéhoZdroje, e);
+ } catch (SQLException e) {
+ throw new BadRealmException("Nepodařilo se navázat spojení s DB datového zdroje: " + jndiDatovéhoZdroje, e);
}
}
+ }
- /** SQL dotazy */
- sqlHeslo = najdiParametr(parametry, PARAM_SQL_HESLO, "SQL dotaz pro ověření jména a hesla");
- sqlSkupinyUživatele = najdiParametr(parametry, PARAM_SQL_SKUPINY_UŽIVATELE, "SQL dotaz pro zjištění skupin uživatele");
- sqlSkupinyVšechny = najdiParametr(parametry, PARAM_SQL_SKUPINY_VŠECHNY, "SQL dotaz pro zjištění všech skupin");
+ private Connection getSpojení() throws NamingException, SQLException {
+ InitialContext k = new InitialContext();
+ DataSource datovýZdroj = (DataSource) k.lookup(jndiDatovéhoZdroje);
+ return datovýZdroj.getConnection();
+ }
- _logger.log(Level.INFO, "SQLRealm úspěšně vytvořen. JaasContext: {0}", jaasContext);
- }
-
@Override
public String getAuthType() {
return AUTH_TYPE;
@@ -83,15 +141,41 @@
*/
@Override
public Enumeration getGroupNames(String uživatel) throws NoSuchUserException {
+ try {
+ return getSkupiny(sqlSkupinyUživatele, uživatel);
+ } catch (NamingException | SQLException e) {
+ String hláška = "Chyba při zjišťování skupin uživatele: " + uživatel + ".";
+ _logger.log(Level.WARNING, hláška, e);
+ throw new NoSuchUserException(hláška);
+ }
+ }
+
+ /**
+ * @return seznam všech skupin v této bezpečnostní doméně
+ * @throws BadRealmException v případě SQL chyby
+ */
+ @Override
+ public Enumeration getGroupNames() throws BadRealmException {
+ try {
+ return getSkupiny(sqlSkupinyVšechny, null);
+ } catch (NamingException | SQLException e) {
+ throw new BadRealmException("Chyba při zjišťování seznamu všech skupin.", e);
+ }
+ }
+
+ public Enumeration getSkupiny(String sql, String parametr) throws SQLException, NamingException {
Collection skupiny = new ArrayList<>();
Connection s = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
- s = datovýZdroj.getConnection();
- ps = s.prepareStatement(sqlSkupinyUživatele);
- ps.setString(1, uživatel);
+ s = getSpojení();
+
+ ps = s.prepareStatement(sql);
+ if (parametr != null) {
+ ps.setString(1, parametr);
+ }
rs = ps.executeQuery();
while (rs.next()) {
@@ -99,18 +183,13 @@
}
return Collections.enumeration(skupiny);
-
- } catch (Exception e) {
- String hláška = "Chyba při zjišťování skupin uživatele: " + uživatel + ".";
- _logger.log(Level.WARNING, hláška, e);
- throw new NoSuchUserException(hláška);
} finally {
zavri(s, ps, rs);
}
}
/**
- *
+ *
* @param jméno uživatelské jméno
* @param heslo heslo
* @return true pokud je jméno a heslo v pořádku | false nikdy – vyhazuje výjimku
@@ -122,7 +201,7 @@
PreparedStatement ps = null;
ResultSet rs = null;
try {
- s = datovýZdroj.getConnection();
+ s = getSpojení();
ps = s.prepareStatement(sqlHeslo);
ps.setString(1, jméno);
ps.setString(2, new String(heslo));
@@ -130,16 +209,16 @@
if (rs.next()) {
String dbJméno = rs.getString(1);
- if (dbJméno.equals(jméno)) {
+ if (dbJméno != null && dbJméno.equals(jméno)) {
// OK – úspěšné ověření
return true;
} else {
- throw new LoginException("Nebyl nalezen správný uživatel: " + jméno + " != " + dbJméno);
+ throw new LoginException("Špatné heslo nebo neexistující uživatel: " + jméno + " != " + dbJméno);
}
} else {
- throw new LoginException("Uživatel nebyl nalezen: " + jméno);
+ throw new LoginException("Špatné heslo nebo neexistující uživatel: " + jméno);
}
- } catch (SQLException e) {
+ } catch (NamingException | SQLException e) {
String hláška = "SQL chyba při ověřování hesla uživatele: " + jméno + ".";
_logger.log(Level.WARNING, hláška, e);
throw new LoginException(hláška);
@@ -148,16 +227,6 @@
}
}
- private String najdiParametr(Properties parametry, String názevParametru, String popis) throws BadRealmException {
- String hodnotaParametru = parametry.getProperty(názevParametru);
-
- if (hodnotaParametru == null || hodnotaParametru.length() < 1) {
- throw new BadRealmException("Chybí " + popis + " – parametr: " + názevParametru);
- } else {
- return hodnotaParametru;
- }
- }
-
/**
* Zavře všechno
*
@@ -170,18 +239,21 @@
try {
vysledek.close();
} catch (Exception e) {
+ _logger.log(Level.FINE, "Při zavírání SQL výsledku došlo k chybě.", e);
}
}
if (prikaz != null) {
try {
prikaz.close();
} catch (Exception e) {
+ _logger.log(Level.FINE, "Při zavírání SQL příkazu došlo k chybě.", e);
}
}
if (spojeni != null) {
try {
spojeni.close();
} catch (Exception e) {
+ _logger.log(Level.FINE, "Při zavírání SQL spojení došlo k chybě.", e);
}
}
}