poniedziałek, 5 stycznia 2009

Zabezpieczenie strony przy użyciu JAAS

Odpowiednie zabezpieczenie strony jest bardzo ważnym aspektem pisania projektu, nie chcemy przecież, aby przypadkowe osoby miały dostęp do funkcji zarządzających naszą strona/baza danych. W celu uwierzytelnienia i autoryzacji użytkowników posłużymy się narzędziem Java Authentication and Authorization Service, w skrócie JAAS.
Zacznijmy od zdefiniowania połączenia z naszą bazą, to co opisywał Dominik w swoim poście. Mój plik mysql-ds.xml wygląda następująco:

<datasources>
<local-tx-datasource>
<jndi-name>myBase</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/sklep</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password></password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>

Następnie w pliku <nasz_jboss>/server/default/conf/login-config.xml dodajemy wpis:

<application-policy name="sklepDomain">
<authentication>
<login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
<module-option name="dsJndiName">java:/myBase</module-option>
<module-option name="principalsQuery">select password from osoba where login=?</module-option>
<module-option name="rolesQuery">select rola,'Roles' from role where login=? </module-option>
<module-option name="debug">true</module-option>
</login-module>
</authentication>
</application-policy>

Widzimy w tym pliku zapytania do bazy danych, tak więc przydałoby się teraz zdefiniować odpowiednie encje. W moim przypadku mamy 2 tabele, pierwsza przechowuje login oraz hasło usera, a druga login i role tego usera. Tak wiec encja Osoba musi zawierać pola tekstowe: login oraz password, a encja Role pola: login oraz rola.
Przechodzimy teraz do warstwy web'owej naszej aplikacji. W folderze WEB-INF tworzymy plik jboss-web.xml i wpisujemy:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>java:/jaas/sklepDomain</security-domain>
</jboss-web>

Przy czym "sklepDomain" pochodzi z pliku login-config.xml
Teraz musimy zdefiniować które obszary naszej strony będą chronione oraz kto będzie miał do nich dostęp, a także gdzie znajdują się strony do logowania oraz w przypadku błędu logowania strona z błędem, trzeba także poinformować jakie role mamy zdefiniowane w naszej aplikacji. W tym celu w pliku web.xml dodajemy:

<security-constraint>
<web-resource-collection>
<web-resource-name>WRC1</web-resource-name>
<url-pattern>/faces/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>FORM</auth-method>
<realm-name>sklepDomain</realm-name>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/loginError.html</form-error-page>
</form-login-config>
</login-config>

<security-role>
<role-name>admin</role-name>
</security-role>

Nie pozostaje nam nic innego jak napisać formularz logowania:

<html>
<body>
<form action="j_security_check" method="post">
<input type="text" name="j_username" /><br />
<input type="password" name="j_password" /><br />
<input type="submit" value="login" />
</form>
</body>
</html>

I to wszystko :) Teraz próbując wejść na którąkolwiek ze stron z folderu protected zostaniemy przeniesieni na stronę logowania, tylko osoba z rola admin będzie mogła tam wejść.

update:
Razem z Dominikiem wykminiliśmy jak jak obsługiwać hasło haszowane algorytmem md5.
Dodajemy do pliku login-config.xml:

<module-option name="hashAlgorithm">MD5</module-option>
<module-option name="hashEncoding">base64</module-option>

Zmodyfikujemy także nieco funkcje podaną w poprzednim poście, która haszowala nasze hasło.
Teraz będzie wyglądać następująco:

private String makeMD5(String pass) throws NoSuchAlgorithmException
{
MessageDigest md = null;
String passwordHash = new String("");

try {
md = MessageDigest.getInstance("MD5");
byte[] passwordBytes = pass.getBytes();
byte[] hash = md.digest(passwordBytes);
passwordHash = Base64Encoder.encode(hash);
}catch (Exception e) {
e.printStackTrace();
}
return passwordHash;
}

4 komentarze:

  1. Boski tut - oszczedzil wielu gozdin kopania w dokumentacji dzieki ;)

    OdpowiedzUsuń
  2. nie chcę się czepiać tylko tak wskazać że trzeba pozamykać te tagi w formularzu ;) np
    a nie

    OdpowiedzUsuń
  3. jeden szczegół...:

    w web.xml tam gdzie określamy stronę z logowaniem i stronę z errorem (login.html i loginError.html)
    nazwy tych stron powinny być poprzedzone slashem '/' czyli:
    /login.html
    /loginError.html
    pozdr :)

    OdpowiedzUsuń