Tomcat: аутентификация пользователей с помощью JDBCRealm и MySQL или Oracle

Автор: | 12/16/2013
 

apache-tomcat-7-logoApache Tomcat имеет несколько механизмов аутентификации. По-умолчанию используется UserDatabaseRealm, который использует данные из файла ../conf/tomcat-users.xml.

Задача — перенастроить Tomcat на использование механизма JDBCRealm с использованием базы данных (MySQL, Oracle).

Для примера возьмём такие настройки пользователя и его роли (группы):

$ cat conf/tomcat-users.xml | grep index
<role rolename="indexadmin"/>
<user username="indexadmin" password="password" roles="indexadmin"/>

Настройки ограничения доступа заданы в файле web.xml, и описаны так:

<security-constraint>

<web-resource-collection>
<web-resource-name>Restricted Area</web-resource-name>
<url-pattern>/index.jsp</url-pattern>
</web-resource-collection>

<auth-constraint>
<role-name>indexadmin</role-name>
</auth-constraint>

</security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>JDBCRealm</realm-name>
</login-config>

<security-role>
<role-name>indexadmin</role-name>
</security-role>

Подробнее о назначении элементов в статье Tomcat: ограничение доступа с помощью файла web.xml.

Тут — мы ограничиваем доступ к файлу index.jsp в корневой директории сервера, для аутентификации будем использовать BASIC (логин/пароль, которые надо будет вводить в окне браузера), доступ к файлу будет разрешён членам группы indexadmin.

Качаем драйвер JDBCR.

Для MySQL:

http://dev.mysql.com/downloads/connector/j/

Для Oracle:

http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html

В данном случае использовались ojdbc6.jar и mysql-connector-java-5.1.27.

Копируем архив с драйвером (только *.jar файл) в каталог ../server/lib/:

$ cp Opt/mysql-connector-java-5.1.27-bin.jar apache-tomcat-5.5.36_ssl_test/server/lib/

Создаём базу данных для MySQL:

mysql> create database tmc_access;
Query OK, 1 row affected (0.03 sec)
mysql> use tmc_access;
Database changed

Создаём таблицу, в которой будем хранить логины/пароли пользователей:

mysql> create table users (user_name varchar(100) not null primary key, user_pass varchar(100) not null);
Query OK, 0 rows affected (0.08 sec)

Таблицу ролей:

mysql> create table user_roles (user_name varchar(100) not null, role_name varchar(100) not null, primary key (user_name, role_name));
Query OK, 0 rows affected (0.00 sec)

Oracle:

SQL> create table users (user_name varchar(100) not null primary key, user_pass varchar(100) not null);
Table created.

Oracle:

SQL> create table user_roles (user_name varchar(100) not null, role_name varchar(100) not null, primary key (user_name, role_name));

Table created.

Создаём пользователя, под которым Tomcat будет работать с базой, привилегий SELECT достаточно:

mysql> grant select on tmc_access.* to 'tmc_access'@'%' identified by 'password';
Query OK, 0 rows affected (0.15 sec)

Таблицы выглядят так:

MySQL:

mysql> desc user_roles;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| user_name | varchar(100) | NO   | PRI | NULL    |       |
| role_name | varchar(100) | NO   | PRI | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
2 rows in set (0.02 sec)
mysql> desc users;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| user_name | varchar(100) | NO   | PRI | NULL    |       |
| user_pass | varchar(100) | NO   |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

Oracle:

SQL> desc users;
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
USER_NAME                                 NOT NULL VARCHAR2(100)
USER_PASS                                 NOT NULL VARCHAR2(100)
SQL> desc user_roles;
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
USER_NAME                                 NOT NULL VARCHAR2(100)
ROLE_NAME                                 NOT NULL VARCHAR2(100)

Добавим пользователя indexadmin с паролем password:

MySQL:

mysql> insert into users (user_name, user_pass) values ('indexadmin', 'password');
Query OK, 1 row affected (0.02 sec)

Добавим роль indexadmin, и назначим её пользователю indexadmin:

mysql> insert into user_roles (user_name, role_name) values ('indexadmin', 'indexadmin');
Query OK, 1 row affected (0.02 sec)

Oracle:

SQL> insert into users (user_name, user_pass) values ('indexadmin', 'password');

1 row created.
SQL> insert into user_roles (user_name, role_name) values ('indexadmin', 'indexadmin');

1 row created.

Проверим:

MySQL:

mysql> select * from user_roles;
+------------+------------+
| user_name  | role_name  |
+------------+------------+
| indexadmin | indexadmin |
+------------+------------+
1 row in set (0.00 sec)
mysql> select * from users;
+------------+-----------+
| user_name  | user_pass |
+------------+-----------+
| indexadmin | password  |
+------------+-----------+
1 row in set (0.00 sec)

Oracle:

SQL> select * from users;

USER_NAME
--------------------------------------------------------------------------------
USER_PASS
--------------------------------------------------------------------------------
indexadmin
password
SQL> select * from user_roles;

USER_NAME
--------------------------------------------------------------------------------
ROLE_NAME
--------------------------------------------------------------------------------
indexadmin
indexadmin

Для Oracle не забываем выполнить комит:

SQL> commit;

Commit complete.

Переходим к настройке самого Tomcat.

Комментируем часть, где описывается Realm по-умолчанию, его мы использовать не будем вообще:

<!--      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/> -->

Далее, для MySQL, раскомментируем и отредактируем блок:

<Realm  className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://10.***.***.239/tmc_access"
connectionName="tmc_access" connectionPassword="password"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name" />

Тут:

driverName= — полное имя драйвера, обычно уже есть в файле;
connectionURL= — адрес сервера и база данных;
connectionName= — логин пользователя базы данных;
connectionPassword= — его пароль;
userTable= — таблица с логинами/паролями пользователей;
userNameCol= — колонка с логинами;
userCredCol= — с паролями;
userRoleTable= — таблица с ролями;
roleNameCol= — колонка таблицы, содержащая имена ролей.

Для Oracle — практически тоже самое:

<Realm  className="org.apache.catalina.realm.JDBCRealm"
driverName="oracle.jdbc.driver.OracleDriver"
connectionURL="jdbc:oracle:thin:@oraclehost:1521:schemename"
connectionName="DBusername" connectionPassword="DBuserpass"
userTable="tmc_users_set" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles_set" roleNameCol="role_name" />

Сохраняем файл, и перезапускаем Tomcat. В процессах MySQL должен появится запрос:

mysql> SHOW FULL PROCESSLISTG
...
*************************** 20. row ***************************
Id: 1750340
User: tmc_access
Host: thucydides:24272
db: tmc_access
Command: Sleep
Time: 1
State:
Info: NULL

В случае проблем — смотрим файл ../logs/catalina.out.

Наиболее частые — это если неверно указаны параметры подключения к серверу баз данных, или неверная база/таблица:

Dec 16, 2013 1:43:13 PM org.apache.catalina.realm.JDBCRealm authenticate
SEVERE: Exception performing authentication
java.sql.SQLException: ORA-01017: invalid username/password; logon denied

// неверный логин/пароль для доступа к базе данных

Dec 16, 2013 1:16:25 PM org.apache.catalina.realm.JDBCRealm authenticate
SEVERE: Exception performing authentication
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

// неверный адрес сервера MySQL, возможно — он прослушивает внешний IP сервера, а не localhost/127.0.0.1, можно проверить:

# netstat -anp | grep mysql
tcp        0      0 10.***.***.239:3306         0.0.0.0:*                   LISTEN      27084/mysqld
Dec 16, 2013 12:14:00 PM org.apache.catalina.startup.ContextConfig applicationWebConfig
SEVERE: Parse error in application web.xml file at jndi:/localhost/WEB-INF/web.xml
java.lang.IllegalArgumentException: Invalid <url-pattern> index.jsp in security constraint

// ошибка в описании <url-pattern>, файл необходимо указывать от корня webapps/ROOT, т.е. со слешом /

Ссылки по теме:

http://tomcat.apache.org
http://tomcat.apache.org
http://josescalia.wordpress.com