franta-hg@2: package cz.frantovo.jaas.sql; franta-hg@2: franta-hg@2: import com.sun.appserv.security.AppservRealm; franta-hg@4: import com.sun.enterprise.security.auth.realm.BadRealmException; franta-hg@4: import com.sun.enterprise.security.auth.realm.NoSuchRealmException; franta-hg@2: import com.sun.enterprise.security.auth.realm.NoSuchUserException; franta-hg@6: import java.sql.Connection; franta-hg@6: import java.sql.PreparedStatement; franta-hg@6: import java.sql.ResultSet; franta-hg@6: import java.sql.SQLException; franta-hg@6: import java.sql.Statement; franta-hg@6: import java.util.ArrayList; franta-hg@6: import java.util.Collection; franta-hg@6: import java.util.Collections; franta-hg@2: import java.util.Enumeration; franta-hg@4: import java.util.Properties; franta-hg@4: import java.util.logging.Level; franta-hg@6: import javax.naming.InitialContext; franta-hg@6: import javax.naming.NamingException; franta-hg@4: import javax.security.auth.login.LoginException; franta-hg@6: import javax.sql.DataSource; franta-hg@2: franta-hg@2: /** franta-hg@6: * Bezpečnostní doména. Uživatelé jsou uloženi v SQL databázi. franta-hg@6: * franta-hg@2: * @author fiki franta-hg@2: */ franta-hg@2: public class SQLRealm extends AppservRealm { franta-hg@2: franta-hg@4: private static final String AUTH_TYPE = "Ověřuje uživatele proti SQL databázi."; franta-hg@6: private static final String PARAM_JNDI = "jndi"; franta-hg@6: private static final String PARAM_SQL_HESLO = "sql_heslo"; franta-hg@6: private static final String PARAM_SQL_SKUPINY_UŽIVATELE = "sql_skupiny_uzivatele"; franta-hg@6: private static final String PARAM_SQL_SKUPINY_VŠECHNY = "sql_skupiny_vsechny"; franta-hg@6: private DataSource datovýZdroj; franta-hg@6: private String sqlHeslo; franta-hg@6: private String sqlSkupinyUživatele; franta-hg@6: private String sqlSkupinyVšechny; franta-hg@4: franta-hg@6: /** franta-hg@6: * Načteme a zkontrolujeme parametry franta-hg@6: * franta-hg@6: * @param parametry franta-hg@6: * @throws BadRealmException pokud je v parametrech chyba franta-hg@6: * @throws NoSuchRealmException franta-hg@6: */ franta-hg@2: @Override franta-hg@4: public void init(Properties parametry) throws BadRealmException, NoSuchRealmException { franta-hg@4: super.init(parametry); franta-hg@4: franta-hg@4: String jaasContext = parametry.getProperty(JAAS_CONTEXT_PARAM, SQLLoginModul.VÝCHOZÍ_JAAS_KONTEXT); franta-hg@4: setProperty(JAAS_CONTEXT_PARAM, jaasContext); franta-hg@4: franta-hg@6: /** Databázové spojení */ franta-hg@6: { franta-hg@6: String jndi = najdiParametr(parametry, PARAM_JNDI, "název datového zdroje"); franta-hg@6: try { franta-hg@6: InitialContext k = new InitialContext(); franta-hg@6: jndi = parametry.getProperty(PARAM_JNDI); franta-hg@6: datovýZdroj = (DataSource) k.lookup(jndi); franta-hg@6: } catch (NamingException e) { franta-hg@6: throw new BadRealmException("Datový zdroj s tímto názvem nebyl nalezen: " + jndi, e); franta-hg@6: } franta-hg@6: } franta-hg@6: franta-hg@6: /** SQL dotazy */ franta-hg@6: sqlHeslo = najdiParametr(parametry, PARAM_SQL_HESLO, "SQL dotaz pro ověření jména a hesla"); franta-hg@6: sqlSkupinyUživatele = najdiParametr(parametry, PARAM_SQL_SKUPINY_UŽIVATELE, "SQL dotaz pro zjištění skupin uživatele"); franta-hg@6: sqlSkupinyVšechny = najdiParametr(parametry, PARAM_SQL_SKUPINY_VŠECHNY, "SQL dotaz pro zjištění všech skupin"); franta-hg@6: franta-hg@6: _logger.log(Level.INFO, "SQLRealm úspěšně vytvořen. JaasContext: {0}", jaasContext); franta-hg@2: } franta-hg@6: franta-hg@2: @Override franta-hg@4: public String getAuthType() { franta-hg@4: return AUTH_TYPE; franta-hg@4: } franta-hg@4: franta-hg@4: /** franta-hg@4: * @param uživatel přihlašovací jméno uživatele franta-hg@4: * @return seznam skupin, ve kterých se daný uživatel nachází franta-hg@4: * @throws NoSuchUserException když uživatel s tímto jménem neexistuje. franta-hg@4: */ franta-hg@4: @Override franta-hg@6: public Enumeration getGroupNames(String uživatel) throws NoSuchUserException { franta-hg@6: Collection skupiny = new ArrayList<>(); franta-hg@6: franta-hg@6: Connection s = null; franta-hg@6: PreparedStatement ps = null; franta-hg@6: ResultSet rs = null; franta-hg@6: try { franta-hg@6: s = datovýZdroj.getConnection(); franta-hg@6: ps = s.prepareStatement(sqlSkupinyUživatele); franta-hg@6: ps.setString(1, uživatel); franta-hg@6: rs = ps.executeQuery(); franta-hg@6: franta-hg@6: while (rs.next()) { franta-hg@6: skupiny.add(rs.getString(1)); franta-hg@6: } franta-hg@6: franta-hg@6: return Collections.enumeration(skupiny); franta-hg@6: franta-hg@6: } catch (Exception e) { franta-hg@6: String hláška = "Chyba při zjišťování skupin uživatele: " + uživatel + "."; franta-hg@6: _logger.log(Level.WARNING, hláška, e); franta-hg@6: throw new NoSuchUserException(hláška); franta-hg@6: } finally { franta-hg@6: zavri(s, ps, rs); franta-hg@6: } franta-hg@4: } franta-hg@4: franta-hg@4: /** franta-hg@4: * franta-hg@4: * @param jméno uživatelské jméno franta-hg@4: * @param heslo heslo franta-hg@6: * @return true pokud je jméno a heslo v pořádku | false nikdy – vyhazuje výjimku franta-hg@6: * @throws LoginException pokud je jméno nebo heslo neplatné nebo došlo k jiné chybě franta-hg@4: */ franta-hg@6: public boolean ověřUživatele(String jméno, char[] heslo) throws LoginException { franta-hg@4: franta-hg@6: Connection s = null; franta-hg@6: PreparedStatement ps = null; franta-hg@6: ResultSet rs = null; franta-hg@6: try { franta-hg@6: s = datovýZdroj.getConnection(); franta-hg@6: ps = s.prepareStatement(sqlHeslo); franta-hg@6: ps.setString(1, jméno); franta-hg@6: ps.setString(2, new String(heslo)); franta-hg@6: rs = ps.executeQuery(); franta-hg@4: franta-hg@6: if (rs.next()) { franta-hg@6: String dbJméno = rs.getString(1); franta-hg@6: if (dbJméno.equals(jméno)) { franta-hg@6: // OK – úspěšné ověření franta-hg@6: return true; franta-hg@6: } else { franta-hg@6: throw new LoginException("Nebyl nalezen správný uživatel: " + jméno + " != " + dbJméno); franta-hg@6: } franta-hg@6: } else { franta-hg@6: throw new LoginException("Uživatel nebyl nalezen: " + jméno); franta-hg@6: } franta-hg@6: } catch (SQLException e) { franta-hg@6: String hláška = "SQL chyba při ověřování hesla uživatele: " + jméno + "."; franta-hg@6: _logger.log(Level.WARNING, hláška, e); franta-hg@6: throw new LoginException(hláška); franta-hg@6: } finally { franta-hg@6: zavri(s, ps, rs); franta-hg@6: } franta-hg@6: } franta-hg@6: franta-hg@6: private String najdiParametr(Properties parametry, String názevParametru, String popis) throws BadRealmException { franta-hg@6: String hodnotaParametru = parametry.getProperty(názevParametru); franta-hg@6: franta-hg@6: if (hodnotaParametru == null || hodnotaParametru.length() < 1) { franta-hg@6: throw new BadRealmException("Chybí " + popis + " – parametr: " + názevParametru); franta-hg@4: } else { franta-hg@6: return hodnotaParametru; franta-hg@6: } franta-hg@6: } franta-hg@6: franta-hg@6: /** franta-hg@6: * Zavře všechno franta-hg@6: * franta-hg@6: * @param spojeni DB spojení franta-hg@6: * @param prikaz DB dotaz franta-hg@6: * @param vysledek DB výsledek franta-hg@6: */ franta-hg@6: private static void zavri(Connection spojeni, Statement prikaz, ResultSet vysledek) { franta-hg@6: if (vysledek != null) { franta-hg@6: try { franta-hg@6: vysledek.close(); franta-hg@6: } catch (Exception e) { franta-hg@6: } franta-hg@6: } franta-hg@6: if (prikaz != null) { franta-hg@6: try { franta-hg@6: prikaz.close(); franta-hg@6: } catch (Exception e) { franta-hg@6: } franta-hg@6: } franta-hg@6: if (spojeni != null) { franta-hg@6: try { franta-hg@6: spojeni.close(); franta-hg@6: } catch (Exception e) { franta-hg@6: } franta-hg@4: } franta-hg@2: } franta-hg@2: }