diff -r e013564c8e6f -r aff44e80f418 java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java --- a/java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java Thu Jul 21 23:41:05 2011 +0200 +++ b/java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java Tue Feb 07 00:27:39 2012 +0100 @@ -4,22 +4,46 @@ 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; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Enumeration; import java.util.Properties; import java.util.logging.Level; -import java.util.logging.Logger; +import javax.naming.InitialContext; +import javax.naming.NamingException; import javax.security.auth.login.LoginException; +import javax.sql.DataSource; /** - * Bezpečnostní doména. - * Uživatelé jsou uloženi v SQL databázi. + * Bezpečnostní doména. Uživatelé jsou uloženi v SQL databázi. + * * @author fiki */ public class SQLRealm extends AppservRealm { private static final String AUTH_TYPE = "Ověřuje uživatele proti SQL databázi."; - private static final Logger log = Logger.getLogger(SQLRealm.class.getName()); + 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; + 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); @@ -27,9 +51,26 @@ String jaasContext = parametry.getProperty(JAAS_CONTEXT_PARAM, SQLLoginModul.VÝCHOZÍ_JAAS_KONTEXT); setProperty(JAAS_CONTEXT_PARAM, jaasContext); - log.log(Level.INFO, "SQLRealm úspěšně vytvořen. JaasContext: {0}", jaasContext); + /** Databázové spojení */ + { + String jndi = najdiParametr(parametry, PARAM_JNDI, "název datového zdroje"); + try { + InitialContext k = new InitialContext(); + jndi = parametry.getProperty(PARAM_JNDI); + datovýZdroj = (DataSource) k.lookup(jndi); + } catch (NamingException e) { + throw new BadRealmException("Datový zdroj s tímto názvem nebyl nalezen: " + jndi, 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"); + + _logger.log(Level.INFO, "SQLRealm úspěšně vytvořen. JaasContext: {0}", jaasContext); } - + @Override public String getAuthType() { return AUTH_TYPE; @@ -41,24 +82,107 @@ * @throws NoSuchUserException když uživatel s tímto jménem neexistuje. */ @Override - public Enumeration getGroupNames(String uživatel) throws NoSuchUserException { - throw new NoSuchUserException("Metoda zatím není implementována. Uživatel: " + uživatel); + public Enumeration getGroupNames(String uživatel) throws NoSuchUserException { + 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); + rs = ps.executeQuery(); + + while (rs.next()) { + skupiny.add(rs.getString(1)); + } + + 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 seznam skupin, do kterých uživatel patří + * @return true pokud je jméno a heslo v pořádku | false nikdy – vyhazuje výjimku + * @throws LoginException pokud je jméno nebo heslo neplatné nebo došlo k jiné chybě */ - public String[] ověřUživatele(String jméno, char[] heslo) throws LoginException { + public boolean ověřUživatele(String jméno, char[] heslo) throws LoginException { - // TODO: skutečně ověřovat heslo proti databázi + Connection s = null; + PreparedStatement ps = null; + ResultSet rs = null; + try { + s = datovýZdroj.getConnection(); + ps = s.prepareStatement(sqlHeslo); + ps.setString(1, jméno); + ps.setString(2, new String(heslo)); + rs = ps.executeQuery(); - if (heslo != null && heslo.length == 3) { - return new String[]{"bezny"}; + if (rs.next()) { + String dbJméno = rs.getString(1); + if (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); + } + } else { + throw new LoginException("Uživatel nebyl nalezen: " + jméno); + } + } catch (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); + } finally { + zavri(s, ps, rs); + } + } + + 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 { - throw new LoginException("Heslo musí mít tři znaky :-P"); + return hodnotaParametru; + } + } + + /** + * Zavře všechno + * + * @param spojeni DB spojení + * @param prikaz DB dotaz + * @param vysledek DB výsledek + */ + private static void zavri(Connection spojeni, Statement prikaz, ResultSet vysledek) { + if (vysledek != null) { + try { + vysledek.close(); + } catch (Exception e) { + } + } + if (prikaz != null) { + try { + prikaz.close(); + } catch (Exception e) { + } + } + if (spojeni != null) { + try { + spojeni.close(); + } catch (Exception e) { + } } } }