My name is Vasyl Khrystiuk‎ > ‎process‎ > ‎main‎ > ‎

4 j2ee webapp security

Структура цикла:
  1. Intro - о чем вообще речь
  2. Risks in web-apps
  3. Java app security - что ява предлагает из коробки для защиты приложений
  4. j2ee webapp security - что ява предлагает из коробки для защиты веб приложений
  5. Auth and auth flow, remember me, access managers models(role-based, unix fs ownership based, vote-based)
  6. custom auth framework
  7. spring security and friends(Apache Shiro)


хуйня все это

http://docs.oracle.com/javaee/6/tutorial/doc/bnbwk.html
открыл
пролистал
закрыл

пару моментов:
есть реалм(security domain) - это база бользователей, на сервере может быть несколько реалмов
есть пользователи
есть группы пользователей(но не на всех серверах, а учитывая, что сейчас речь идеть о каноничесском j2ee, то это еще вопрос, нужно ли оно мне)
есть роли - это абстрактное имя для набора разрешений


в j2ee компонентах(j2ee бинах?) есть аннотации
javax.annotation.security.DeclareRoles;
javax.annotation.security.RolesAllowed;
@PermitAll
@DenyAll

данные хранятся в @Resource SessionContext ctx;

вопрос - работают ли они для приложений без j2ee бинов

еще есть аннотации для сервлетов:
@WebServlet(name = "PayrollServlet", urlPatterns = {"/payroll"})
@ServletSecurity(
@HttpConstraint(transportGuarantee = TransportGuarantee.CONFIDENTIAL,
rolesAllowed = {"DEPT-ADMIN", "DIRECTOR"}))
public class GreetingServlet extends HttpServlet {
@HttpConstraint, @HttpMethodConstraint, @ServletSecurity


тут сразу несколько вопросов:
1) снова таки, есть ли это в j2ee который без j2ee бинов?
2) какая версия должан быть у конфигурации веблирожения
3) как контролировать поиск этох аннотаций(как огланичить/расширить места для поиска)
есть догадка что ответ на третий вопрос - сервлет специфичесский(как почти и у всего j2ee г-на)
потому что для jetty я нашел это:
<?xml version="1.0" encoding="UTF-8"?>
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
 <Call name="setAttribute">
  <Arg>org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</Arg>
  <Arg>^$</Arg>
 </Call>
</Configure>
продолжаем
A role can be mapped to specific principals, specific groups, or both:
<glassfish-web-app> ...
<security-role-mapping>
<role-name>Mascot</role-name>
<principal-name>Duke</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>Admin</role-name>
<group-name>Director</group-name>
</security-role-mapping>
... </glassfish-web-app>



продолжаем:
HttpServletRequest из спецификация servlet 3.0 ВНЕЗАПНО имеет такие вот интерестные методы:
"authenticate, login, and logout"
пруф:
 https://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/http/HttpServletRequest.html
и эти методы там существуют с 2009 года(а на сегодня уже даже стандартизоован набор servlet 3.1 из java7)
и там вообще много добавили, например, щас смотрю 3.1, так так есть такие методы как: isSecure(), startAsync(), и прочие, но всем понятно, что использовать эти возможности будут не скоро

Upd: 
Попробовал я это и есть одна вещь, от которой меня просто рвет.  Перед тем как описать что мы имеем, я хочу описать что я хочу. А я хочу простого - создать защищенный ресурс и создать одного пользователя, который будет иметь доступ к этому ресурсу. Понятно что для пользователя нужно указать логин и пароль. Теперь что же мы имеем:
Внимание - учетные данные для доступа ХРАНЯТСЯ В КАЖДОМ СЕРВЛЕТ КОНТЕЙНЕРЕ ПО СВОЕМУ
Даже больше - ОНИ РЕКОМЕНДУЮТ ИСПОЛЬЗОВАТЬ АУТЕНТИФИКАЦИЮ КОНТЕЙНЕРА
>In general, security management should be enforced by the container in a manner that is transparent to the web component
ну охуеть теперь

От одного осознания этого факта я просто безумствую. Ок. Сегодня наш гость - GlassFish. Попробуем настроить его. Этот процесс настолько увлекательный... Начнем с того, что просто так создать пользователя в web.xml  я не могу. Почему? Дальше. Пользователи в glassfish создаются через админ консоль, которая является вебприложением. Нипанимать. Хотя, вроде все логично - вот тебе админ консоль, создавай пользователя и пользуйся. Ну. Да. Это годно. Это просто. Сервер это программа. Ты просто открываешь настройки программы и добавляешь туда пользователей. Что мне в этом не нравится - то, что это не unix-way. Я не против красивой тулзы, но я бы хотел знать. что и где она меняет, где на самом деле хранятся учетные записи, и могу ли я открыть текстовый файл(или два) и внести нужные изменения, не используя никаких инструментов.  
Продолжим. 
Есть еще способ, уже лучше.
asadmin
В папке с сервером в поддериктории bin находится asadmin.bat, которая предназначена для выполнения административных задач. Она имеет довольно богатый набор команд, в том числе, возможность вызова этих команд через веб-апи(что-то такое промелькнуло, не было желания разбираться(http://localhost:4848/__asadmin/restart-domain) <- рабочий пример ), так и возможность програмного использования(тут не понятно - то ли программа должна быть локальной на компьютере, то ли это апи для выполнения административных задач изнутри контейнера. Пример ниже:
Example 8 Running an asadmin create-jdbc-resource Command

This example shows code for running an asadmin create-jdbc-resource command. Code for creating and starting the server is not shown in this example. For an example of code for creating and starting the server, see Example 4.

...
import org.glassfish.api.embedded.*;
import org.glassfish.api.admin.*;
...
    String command = "create-jdbc-resource";
    ParameterMap params = new ParameterMap();
    params.add("connectionpoolid", "DerbyPool");
    params.add("jndi_name", "jdbc/DerbyPool");
    CommandRunner runner = server.getHabitat().getComponent(CommandRunner.class);
    ActionReport report = server.getHabitat().getComponent(ActionReport.class);
    runner.getCommandInvocation(command, report).parameters(params).execute();

Это да, уже намного лучше, но все равно не то. 
В общем, не нашел я ответа, задал его на стеке, посмотрим что с этого будет. 
А пока создам пользователя через asadmin, команда create-file-user
А еще экспериментальным путем я узнал, что эта команда создает запись в файле 
glassfish-4.1\glassfish\domains\localhost\config\keyfile
в формате логин;{passw-algo}passw_hash
Уже лучше, но все равно не то , ибо я конфигурирую приложение, а файлик с конфигурацией создается на сервере, но ведь приложение это не сервер, хотя может есть способы деплоить этот файлик из приложения на сервер во время развертывания. Не хочу углубляться. Есть дока, вряд ли я в здравом уме для себя к этому вернусь: http://docs.oracle.com/cd/E18930_01/html/821-2416/ggjxp.html




security-constraint в себе могут содержание таких элементов:
  • Web resource collection (web-resource-collection): A list of URL patterns (the part of a URL afterthe host name and port you want to constrain) and HTTP operations (the methods within the files that match the URL pattern you want to constrain) that describe a set of resources to be protected. A web resource collection consists of the following subelements:
    • web-resource-name is the name you use for this resource. Its use is optional.
    • url-pattern is used to list the request URI to be protected. 
    • http-method or http-method-omission
  • Authorization constraint (auth-constraint): Specifies whether authentication is to be used and names the roles authorized to perform the constrained requests. 
    • Each role name specified here must either correspond to the role name of one of the security-role elements defined for this web application or be the specially reserved role name *, which indicates all roles in the web application. Role names are case sensitive.
    • For a servlet, the @HttpConstraint and @HttpMethodConstraint annotations accept a rolesAllowed element that specifies the authorized roles.
  • User data constraint (user-data-constraint): HTTPS(SSL). Specifies how data is protected when transported between a client and a server.
    • Specify CONFIDENTIAL when the application requires that data be transmitted so as to prevent other entities from observing the contents of the transmission.
    • Specify INTEGRAL when the application requires that the data be sent between client and server in such a way that it cannot be changed in transit.
    • Specify NONE to indicate that the container must accept the constrained requests on any connection, including an unprotected one.
Еще одно очень полезное замечание по поводу сессий:

Note – After you switch to SSL for a session, you should never accept any non-SSL requests for the rest of that session. For example, a shopping site might not use SSL until the checkout page, and then it might switch to using SSL to accept your card number. After switching to SSL, you should stop listening to non-SSL requests for this session. The reason for this practice is that the session ID itself was not encrypted on the earlier communications. This is not so bad when you’re only doing your shopping, but after the credit card information is stored in the session, you don’t want anyone to use that information to fake the purchase transaction against your credit card. This practice could be easily implemented by using a filter.


example of config:
<!-- SECURITY CONSTRAINT #1 -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>wholesale</web-resource-name>
        <url-pattern>/company/wholesale/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>PARTNER</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint> SecuringWeb Applications 718 The Java EE 6 Tutorial • January 2013

<!-- SECURITY CONSTRAINT #2 -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>retail</web-resource-name>
        <url-pattern>/company/retail/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>CLIENT</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>


Specifying Authentication Mechanisms

капитан очевидность совсем рядом:
Before you can authenticate a user, you must have a database of user names, passwords, and roles configured on your web or application server. 


The Java EE platform supports the following authentication mechanisms:
  • Basic authentication
    • base64-encoded login:password in header
    1. flow: 
      1. (client) -- {req to protected res} --> (sever)
      2. (client)< -- {ask password a nd login} -- (sever)
      3. (client)-- {send passw and login} --> (sever)
      4. (client)<-- {return protected resource} -- (sever)
  • Form-based authentication
    • <form method="POST" action="j_security_check"> <input type="text" name="j_username"> <input type="password" name="j_password"> </form>
  • Digest authentication
    • Digest authentication does not send user passwords over the network. Instead, the client sends a one-way cryptographic hash of the password and additional data. Although passwords are not sent on the wire, digest authentication requires that clear-text password equivalents be available to the authenticating container so that it can validate received authenticators by calculating the expected digest.
  • Client authentication
  • Mutual authentication


Configure auth example:
<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>file</realm-name>
    <form-login-config>
        <form-login-page>/login.xhtml</form-login-page>
        <form-error-page>/error.xhtml</form-error-page>
    </form-login-config>
</login-config>


Constraints example:
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/security/protected/*</url-pattern>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>manager</role-name>
    </auth-constraint>
</security-constraint>

<security-role>
    <role-name>manager</role-name>
</security-role>
<security-role>
    <role-name>employee</role-name>
</security-role>
dfsdf
тут будет код сервлета 3,0
да, и сервлет контейнером будет 
GlassFish
код выше
похуй
говно

Прошло две недели с того момента как я прервался с этим разбором потому что я понял, что ничего не знаю ни о аппликейшин серверах, ни о новинках EJB. Потому эти две недели я потратил на устранение пролетов в моем сознании. В заключение по проделанной работе могу сказать только одно - "я ожидал большего".  
Но не будем вдаваться в подробности. 
Скажу только что спринг секюрити намного лучше.

@RolesAllowed("Users")


нужно посортировать все это


______________________________
отдельно вспомнил, что в книге в разделе об секюрности веб-приложений j2ee упоминалось об возможности использовать jaas framework, однако никакой более инфы там не было. более того, совсем не очевидно, как разработанный для прикладных приложений механизм авторизации можно использовать в клиент-серверном приложении. и это неочевидно не только мне. вот например выдача с гугла по релевантному запросу:


Из неочевидного:
  • как будет работать аутентификейшн калбек в вебприложении и куда его размещать
  • откуда и как будут доставаться данные пользователей
  • кто и как будет регистрировать принципала в контексте вебприложения(особенно учитывая что этот контекст разный у каждого сервера)
  • будет ли соблюдаться безопасность сессий и прочие прелести

Ну, в общем, во первых, в конце книги есть пример с использованием этой самой авторизации, во вторых, как вы уже заметили, в интернете полно примеров.
первая ссылка кстати довольно интересна:
качество кода там очень низкое, но свою задачу он выполняет очень хорошо - он демонстрирует как j2ee в вебприложении может исполняться. 
да и вторая ссылка тоже хороша
К слову, ограничение на выполнения кода по секюрити менеджеру там тоже работает
вот обзору чего то такого как в второй ссылке и должна ьыла бы быть посвящена эта статья НО ЗАТО ТЕПЕРЬ Я ЗНАЮ КАК ЧЕРЕЗ ЖОПУ ДЕЛАЕТСЯ ЭТО НА АППЛИКЕЙШИН СЕРВЕРАХ(или я просто не умею их готовить, или просто мои ожидания не соответствуют действительности ентерпрайза)

краткое пособие по всему из того что выше
http://docs.oracle.com/javaee/6/tutorial/doc/bncbx.html

и еще один интересный вывод:
создавая систему авторизации нужно ориентироваться не только на имя принципала/его роли, но и на его происхождение/тип, ведь вполне вероятна ситуация что через неправильно настроенный сервлет-контейнер/баг в нему или по другим, более административным причинам, на контейнере внезапно будет работать дополнительно собственная аутентификация, которая и будет обеспечивать существование пользователя в то время как его у нас нет

и еще один интересный вывод:
стандарт и платформа j2ee не представляет практически никаких инструментов для обеспечения безопасности вебприложения, кроме как декларативной аутентификации на уровне контейнера(качество и реализация которой, впрочем, желает лучшего), а потому использование ИЛИТНІХ ИНТЕРПРЙС СИЕРВИЕРАВ на самом деле не то что не гарантирует никакой безопасности, более того, оно никак не упрощает создание собственной системы безопасности. Да, база для имплементации есть, но эта база представляет собой голые интерфейсы, которые покрывают некоторую часть безопасности, и то те интерфейсы были написаны почти 15 лет назад. я не говорю что они устарели. они используются как основа и сегодня. но я говорю о том, что с того времени прошло много врмени, и никто не стоит на месте, сейчас например каждый второй python фреймворк покрывает намного больше вопросов по веббезопасности, чем знаменитая j2ee структура


и еще момент:
эти сервера предоставляют возможность мониторить состояние сервера через подключаемые логеры/листнеры контейнара/JMX



значит это еще не конец
еще
PART IX
Case Studies
и 


нет, блять
како     же это всетаки глупый сервер
http://java.dzone.com/articles/hudson-security-manager

Case Studies
для того, чтоб насладиться этим более полноценно я решил пройти Case Studies(там между прочего будет и CDI и Facelets)



Comments