1.1 --- a/java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java Thu Jul 21 23:41:05 2011 +0200
1.2 +++ b/java/sql-java-prihlasovani/src/cz/frantovo/jaas/sql/SQLRealm.java Tue Feb 07 00:27:39 2012 +0100
1.3 @@ -4,22 +4,46 @@
1.4 import com.sun.enterprise.security.auth.realm.BadRealmException;
1.5 import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
1.6 import com.sun.enterprise.security.auth.realm.NoSuchUserException;
1.7 +import java.sql.Connection;
1.8 +import java.sql.PreparedStatement;
1.9 +import java.sql.ResultSet;
1.10 +import java.sql.SQLException;
1.11 +import java.sql.Statement;
1.12 +import java.util.ArrayList;
1.13 +import java.util.Collection;
1.14 +import java.util.Collections;
1.15 import java.util.Enumeration;
1.16 import java.util.Properties;
1.17 import java.util.logging.Level;
1.18 -import java.util.logging.Logger;
1.19 +import javax.naming.InitialContext;
1.20 +import javax.naming.NamingException;
1.21 import javax.security.auth.login.LoginException;
1.22 +import javax.sql.DataSource;
1.23
1.24 /**
1.25 - * Bezpečnostní doména.
1.26 - * Uživatelé jsou uloženi v SQL databázi.
1.27 + * Bezpečnostní doména. Uživatelé jsou uloženi v SQL databázi.
1.28 + *
1.29 * @author fiki
1.30 */
1.31 public class SQLRealm extends AppservRealm {
1.32
1.33 private static final String AUTH_TYPE = "Ověřuje uživatele proti SQL databázi.";
1.34 - private static final Logger log = Logger.getLogger(SQLRealm.class.getName());
1.35 + private static final String PARAM_JNDI = "jndi";
1.36 + private static final String PARAM_SQL_HESLO = "sql_heslo";
1.37 + private static final String PARAM_SQL_SKUPINY_UŽIVATELE = "sql_skupiny_uzivatele";
1.38 + private static final String PARAM_SQL_SKUPINY_VŠECHNY = "sql_skupiny_vsechny";
1.39 + private DataSource datovýZdroj;
1.40 + private String sqlHeslo;
1.41 + private String sqlSkupinyUživatele;
1.42 + private String sqlSkupinyVšechny;
1.43
1.44 + /**
1.45 + * Načteme a zkontrolujeme parametry
1.46 + *
1.47 + * @param parametry
1.48 + * @throws BadRealmException pokud je v parametrech chyba
1.49 + * @throws NoSuchRealmException
1.50 + */
1.51 @Override
1.52 public void init(Properties parametry) throws BadRealmException, NoSuchRealmException {
1.53 super.init(parametry);
1.54 @@ -27,9 +51,26 @@
1.55 String jaasContext = parametry.getProperty(JAAS_CONTEXT_PARAM, SQLLoginModul.VÝCHOZÍ_JAAS_KONTEXT);
1.56 setProperty(JAAS_CONTEXT_PARAM, jaasContext);
1.57
1.58 - log.log(Level.INFO, "SQLRealm úspěšně vytvořen. JaasContext: {0}", jaasContext);
1.59 + /** Databázové spojení */
1.60 + {
1.61 + String jndi = najdiParametr(parametry, PARAM_JNDI, "název datového zdroje");
1.62 + try {
1.63 + InitialContext k = new InitialContext();
1.64 + jndi = parametry.getProperty(PARAM_JNDI);
1.65 + datovýZdroj = (DataSource) k.lookup(jndi);
1.66 + } catch (NamingException e) {
1.67 + throw new BadRealmException("Datový zdroj s tímto názvem nebyl nalezen: " + jndi, e);
1.68 + }
1.69 + }
1.70 +
1.71 + /** SQL dotazy */
1.72 + sqlHeslo = najdiParametr(parametry, PARAM_SQL_HESLO, "SQL dotaz pro ověření jména a hesla");
1.73 + sqlSkupinyUživatele = najdiParametr(parametry, PARAM_SQL_SKUPINY_UŽIVATELE, "SQL dotaz pro zjištění skupin uživatele");
1.74 + sqlSkupinyVšechny = najdiParametr(parametry, PARAM_SQL_SKUPINY_VŠECHNY, "SQL dotaz pro zjištění všech skupin");
1.75 +
1.76 + _logger.log(Level.INFO, "SQLRealm úspěšně vytvořen. JaasContext: {0}", jaasContext);
1.77 }
1.78 -
1.79 +
1.80 @Override
1.81 public String getAuthType() {
1.82 return AUTH_TYPE;
1.83 @@ -41,24 +82,107 @@
1.84 * @throws NoSuchUserException když uživatel s tímto jménem neexistuje.
1.85 */
1.86 @Override
1.87 - public Enumeration getGroupNames(String uživatel) throws NoSuchUserException {
1.88 - throw new NoSuchUserException("Metoda zatím není implementována. Uživatel: " + uživatel);
1.89 + public Enumeration<String> getGroupNames(String uživatel) throws NoSuchUserException {
1.90 + Collection<String> skupiny = new ArrayList<>();
1.91 +
1.92 + Connection s = null;
1.93 + PreparedStatement ps = null;
1.94 + ResultSet rs = null;
1.95 + try {
1.96 + s = datovýZdroj.getConnection();
1.97 + ps = s.prepareStatement(sqlSkupinyUživatele);
1.98 + ps.setString(1, uživatel);
1.99 + rs = ps.executeQuery();
1.100 +
1.101 + while (rs.next()) {
1.102 + skupiny.add(rs.getString(1));
1.103 + }
1.104 +
1.105 + return Collections.enumeration(skupiny);
1.106 +
1.107 + } catch (Exception e) {
1.108 + String hláška = "Chyba při zjišťování skupin uživatele: " + uživatel + ".";
1.109 + _logger.log(Level.WARNING, hláška, e);
1.110 + throw new NoSuchUserException(hláška);
1.111 + } finally {
1.112 + zavri(s, ps, rs);
1.113 + }
1.114 }
1.115
1.116 /**
1.117 *
1.118 * @param jméno uživatelské jméno
1.119 * @param heslo heslo
1.120 - * @return seznam skupin, do kterých uživatel patří
1.121 + * @return true pokud je jméno a heslo v pořádku | false nikdy – vyhazuje výjimku
1.122 + * @throws LoginException pokud je jméno nebo heslo neplatné nebo došlo k jiné chybě
1.123 */
1.124 - public String[] ověřUživatele(String jméno, char[] heslo) throws LoginException {
1.125 + public boolean ověřUživatele(String jméno, char[] heslo) throws LoginException {
1.126
1.127 - // TODO: skutečně ověřovat heslo proti databázi
1.128 + Connection s = null;
1.129 + PreparedStatement ps = null;
1.130 + ResultSet rs = null;
1.131 + try {
1.132 + s = datovýZdroj.getConnection();
1.133 + ps = s.prepareStatement(sqlHeslo);
1.134 + ps.setString(1, jméno);
1.135 + ps.setString(2, new String(heslo));
1.136 + rs = ps.executeQuery();
1.137
1.138 - if (heslo != null && heslo.length == 3) {
1.139 - return new String[]{"bezny"};
1.140 + if (rs.next()) {
1.141 + String dbJméno = rs.getString(1);
1.142 + if (dbJméno.equals(jméno)) {
1.143 + // OK – úspěšné ověření
1.144 + return true;
1.145 + } else {
1.146 + throw new LoginException("Nebyl nalezen správný uživatel: " + jméno + " != " + dbJméno);
1.147 + }
1.148 + } else {
1.149 + throw new LoginException("Uživatel nebyl nalezen: " + jméno);
1.150 + }
1.151 + } catch (SQLException e) {
1.152 + String hláška = "SQL chyba při ověřování hesla uživatele: " + jméno + ".";
1.153 + _logger.log(Level.WARNING, hláška, e);
1.154 + throw new LoginException(hláška);
1.155 + } finally {
1.156 + zavri(s, ps, rs);
1.157 + }
1.158 + }
1.159 +
1.160 + private String najdiParametr(Properties parametry, String názevParametru, String popis) throws BadRealmException {
1.161 + String hodnotaParametru = parametry.getProperty(názevParametru);
1.162 +
1.163 + if (hodnotaParametru == null || hodnotaParametru.length() < 1) {
1.164 + throw new BadRealmException("Chybí " + popis + " – parametr: " + názevParametru);
1.165 } else {
1.166 - throw new LoginException("Heslo musí mít tři znaky :-P");
1.167 + return hodnotaParametru;
1.168 + }
1.169 + }
1.170 +
1.171 + /**
1.172 + * Zavře všechno
1.173 + *
1.174 + * @param spojeni DB spojení
1.175 + * @param prikaz DB dotaz
1.176 + * @param vysledek DB výsledek
1.177 + */
1.178 + private static void zavri(Connection spojeni, Statement prikaz, ResultSet vysledek) {
1.179 + if (vysledek != null) {
1.180 + try {
1.181 + vysledek.close();
1.182 + } catch (Exception e) {
1.183 + }
1.184 + }
1.185 + if (prikaz != null) {
1.186 + try {
1.187 + prikaz.close();
1.188 + } catch (Exception e) {
1.189 + }
1.190 + }
1.191 + if (spojeni != null) {
1.192 + try {
1.193 + spojeni.close();
1.194 + } catch (Exception e) {
1.195 + }
1.196 }
1.197 }
1.198 }