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:

+ * + * + */ + 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:

+ *
    + *
  1. uživatelské jméno
  2. + *
  3. heslo
  4. + *
+ * + *

Vrací:

+ * + * + *

Příklady:

+ * + * + * + *

(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:

+ * + * + */ + 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:

+ * + * + */ + 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); } } }