Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Аутентификация клиентов по Сертификатам, CLIENT-CERT + jbdc Realm 
:(
    Опции темы
drG100k
Дата 14.10.2010, 00:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 31.3.2006

Репутация: нет
Всего: нет



Здравствуйте, столкнулся со связкой jdbc realm и <login-method>CLIENT-CERT</login-method> в одном флаконе.
Конечно всё написано в Java EE Tutorial, но, как всегда "размыто".
Вот, решил собрать всё важное в одном месте, в качестве напоминалки для себя  smile, а заодно может кому ещё пригодится.
Буду писать рецепт для связки Tomcat 6 + Postgresql + Java EE 5/6 Web Application

Для начала нужно создать таблицы в базе данных
Код

create table users (user_name varchar(200) not null primary key, passwd char(1) default null);
create table roles(user_name varchar(200) not null references users(user_name), role_name varchar(100) not null,
 primary key(user_name,role_name));


поле passwd нам не понадобится так как пользователи будут аутентифицироваться по сертификатам. 
Название полей user_name в обеих таблицах лучше сделать одинаковыми.

В Tomcat ${CATALINA-BASE}/conf/server.xml для SSL соединений прописываем 

Код

...
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
           maxThreads="150" scheme="https" secure="true"
           keystoreFile="${user.home}/.keystore" keystorePass="SuperSecretPassword"
           truststoreFile="${user.home}/.truststore" truststorePass="SuperSecretPassword"
           clientAuth="true" sslProtocol="TLS" />
...



Для JDBC Realm
Код

<Realm className="org.apache.catalina.realm.JDBCRealm"
           driverName="org.postgresql.Driver"
           connectionURL="jdbc:postgresql://localhost:5432/mydb"
           username="postgresusername" password="puPassword"
           userTable="users" userNameCol="user_name" userCredCol="passwd"
           userRoleTable="roles" roleNameCol="role_name"/>


Пользователю postgresusername желательно дать права только на чтение.
Для тестов сгенерим пару сертификатов
для сервера 

Код

keytool -genkeypair -alias tomcat-server -keyalg RSA -keysize 1024 -keystore .keystore



Для клиента (в формате, который понимает, например браузер FireFox)
Код

keytool -genkeypair -alias client -keyalg RSA -keysize 1024 -keystore client.p12 -storetype PKCS12

На вопросы keytool ответил так: CN="User#1", OU=Tester, O=Mega Corp, L=SPb, ST=NW, C=RU - эта строка и будет user_name

Так как мы негенерили "левый" сертификат, импортируем его в truststore Сервера
Код

keytool -exportcert -keystore client.p12 -storetype PKCS12 -file client.cer -alias client
keytool -importcert -file client.cer -keystore .truststore

на вопрос доверяем?, отвечаем огга 
Всё, естесственно, из Tomcat ${user.home} 
После этого можно запустить Tomcat и посмотреть в лог, если не сыпятся exception по поводу соединения с базой и отсутствия файлов .keystore, .truststore, то смело переходим к Web Application

Для простоты пусть будет сервлет

Дескриптор web.xml

Код

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     version="3.0">   
    <servlet>
        <display-name>Certificate Servlet Auth</display-name>
        <servlet-name>login</servlet-name>
        <servlet-class>com.org.whatever.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>loginPage</web-resource-name>
            <url-pattern>/login</url-pattern>
            <!-- Все методы -->
            <http-method-omission></http-method-omission>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
        <auth-constraint>
            <role-name>loginRole</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>CLIENT-CERT</auth-method>
    </login-config>
    <security-role>
        <role-name>loginRole</role-name>
    </security-role>
</web-app>



Ну и сам сервлет

Код


package com.org.whatever;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class LoginServlet extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.println("<html>");
            out.println("<body>");
            out.println("<head>");
            out.println("<title>Cert login</title>");
            out.println("</head>");
            out.println("<body bgcolor=\"white\">");
            out.println("<h3> Client logged in</h3>");
            out.println("<table border=0><tr><td>");
            out.println("method:");
            out.println("</td><td>");
            out.println(request.getMethod());
            out.println("</td></tr><tr><td>");
            out.println("url");
            out.println("</td><td>");
            out.println(request.getRequestURL());
            out.println("</td></tr><tr><td>");
            out.println("protocol");
            out.println("</td><td>");
            out.println(request.getProtocol());
            out.println("</td></tr><tr><td>");
            out.println("Is user in loginRole?");
            out.println("</td><td><b>");
            out.println(request.isUserInRole("loginRole") ? "Yes" : "No");
            out.println("</b></td></tr><tr><td>");
            out.println("remote User");
            out.println("</td><td>");
            out.println(request.getRemoteUser());
            out.println("</td></tr><tr><td>");
            String cipherSuite = (String) request.getAttribute("javax.servlet.request.cipher_suite");
            if (cipherSuite != null) {
                out.println("SSLCipherSuite:");
                out.println("</td><td>");
                out.println(cipherSuite);
                out.println("</td></tr><tr><td>");
                out.println("Session Id");
                out.println("</td><td>");
                out.println(request.getAttribute("javax.servlet.request.ssl_session"));
                out.println("</td></tr>");
            }
            out.println("</table>");
            out.println("</body>");
            out.println("</html>");
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
    
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Login Servlet";
    }
}




Осталось забить в базу данных user_name = 'CN="User#1", OU=Tester, O=Mega Corp, L=SPb, ST=NW, C=RU'
role_name = loginRole для этого юзверя

Импортируем client.p12 в браузер и тестим...
    
PM MAIL   Вверх
taro
Дата 19.10.2010, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 29.8.2007

Репутация: нет
Всего: нет



Проект выложите, что ли? 
А то не очень понятно, за что вы боролись. 
PM MAIL   Вверх
0x00
  Дата 22.10.2010, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 192
Регистрация: 3.4.2006

Репутация: нет
Всего: нет



тоже хочется проект увидеть целиком
PM MAIL   Вверх
drG100k
Дата 23.10.2010, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 31.3.2006

Репутация: нет
Всего: нет



Цитата(taro @ 19.10.2010,  09:33)
Проект выложите, что ли? 
А то не очень понятно, за что вы боролись.

Боролся за то чтобы методы в этих строчках  
Код

out.println(request.isUserInRole("loginRole") ? "Yes" : "No");          
out.println(request.getRemoteUser());

не возвращали всегда false и null  со всеми вытекающими... т.е. чтобы работали аннотация @RolesAllowed, метод SessionContext.isCallerInRole(String), EJBContext.getCallerPrincipal() и всякая прочая лабуда, относящаяся к разграничению прав в приложении

Весь проект из 2ух файлов web.xml и сервлет  smile они все выложены
Всё остальное относится к настройкам Tomcat


user posted image
вот такая схема аутентификации

Это сообщение отредактировал(а) drG100k - 23.10.2010, 14:28
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0770 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.