Статьи

Тонкая веб-авторизация в Java с использованием XACML

Контейнеры сервлетов, такие как Tomcat, необходимы для поддержки безопасности контейнеров, которая включает грубую авторизацию на основе ролей. Спецификация сервлета определяет веб-ресурсы в форме шаблонов URL и может обеспечивать контроль доступа к этим ресурсам с помощью ролей. Само по себе это может быть благом или проклятием для веб-разработчиков в зависимости от их вариантов использования. Положительным моментом является то, что разработчики могут изолировать код безопасности от своей бизнес-логики и делегировать безопасность веб-контейнерам. Ограничивающим аспектом является то, что авторизация веб-контейнера плохо масштабируется для удовлетворения потребностей управления бизнес-приложениями в корпоративных приложениях. Oasis XACML v2.0 — это спецификация, которая ориентирована исключительно на управление доступом и является отличной спецификацией для включения мелкозернистого контроля доступа в ваши корпоративные веб-приложения.В этой статье мы рассмотрим включение детальной авторизации в ваше веб-приложение.

 

Мелкозернистый контроль доступа

В отличие от грубого контроля доступа, точный контроль доступа является сложным с изменяющимися требованиями и множеством переменных, участвующих в процессе принятия решений. Решения по управлению доступом, такие как следующие:

  • Разрешить сотрудникам доступ к разделу портала в обычные рабочие дни с 9:00 до 17:00, а не по выходным.
  • Запретить запросы из определенной подсети.
  • Младшие трейдеры нуждаются в одобрении менеджеров для сделок стоимостью более 1 миллиона долларов.
  • Сотрудники не должны изменять собственную информацию о зарплате. Только менеджеры могут изменять информацию о зарплате своих подчиненных.

невозможно сопоставить с правилами управления доступом, указанными в спецификации сервлета. Эти расширенные вопросы контроля доступа основаны на контексте и потребностях бизнеса. Хотя имеет смысл использовать безопасность веб-контейнера для аутентификации и грубой авторизации, безусловно, к сожалению, безопасность контейнера не дотягивает до мелкозернистой авторизации. Одним из возможных решений является экстернализация политики контроля доступа таким образом, чтобы механизм политики, который выполняет оценку, оставался неизменным, а внешние политики могли изменяться в соответствии с требованиями бизнеса. Учитывая это, веб-разработчики обычно разрабатывают безопасность как часть своего приложения. Для них имеет смысл использовать фильтры сервлетов для обеспечения безопасности своих приложений, так что приложение выполняет бизнес-код, а фильтр заботится о безопасности.

 

Списки контроля доступа

Исторически сложилось, что списки ACL позволяли разработчикам и администраторам включать детальную авторизацию в свои бизнес-приложения. Недостатком такого подхода является то , что она является непереносимой и propreitory без каких — либо стандартов , участвующих. XACML предоставляет основанное на стандартах решение этой проблемы.

 

XACML

XACML определяет язык политики и архитектуру для принятия решений. На следующей диаграмме показана базовая архитектура XACML, которая включает в себя точку применения политики (PEP), которая перехватывает любые запросы в обычном потоке программы, а затем просит точку принятия решения политики (PDP) принять решение о доступе на основе политик, связанных с PDP. PDP оценивает запрос XACML, созданный PEP, и проходит через политики, чтобы принять одно из 4 решений о доступе, а именно

  • РАЗРЕШЕНИЕ — утвердить,
  • DENY — доступ запрещен,
  • INDETERMINATE — ошибка в PDP,
  • NOTAPPLICABLE — некоторый атрибут отсутствует в запросе или не соответствует политике.

Реализации XACML на основе Java

В этой статье мы будем использовать JBossXACML, лицензированную библиотеку LGPL для разработки PEP и PDP для нашей детальной авторизации.
JBossXACML — это автономная библиотека с открытым исходным кодом, которая зависит только от реализации JAXB2 (либо вы можете использовать RI Sun JAXB2 для JDK5, либо она предоставляется JDK6 и далее).

Политика XACML

Давайте взглянем на политику XACML, которая послужит основой простого сценария использования в этой статье. Вариант использования — управление доступом к веб-ресурсу, обозначенному URL-адресом « http: //test/developer-guide.html », для субъекта с ролью « разработчика ».

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Policy xmlns="urn:oasis:names:tc:xacml:2.0:policy:schema:os"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:permit-overrides"
Version="2.0" PolicyId="ExamplePolicy">
<Target>
<Resources>
<Resource>
<ResourceMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:anyURI-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#anyURI">http://test/developer-guide.html</AttributeValue>
<ResourceAttributeDesignator DataType="http://www.w3.org/2001/XMLSchema#anyURI" AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"/>
</ResourceMatch>
</Resource>
</Resources>
</Target>
<Rule Effect="Permit" RuleId="ReadRule">
<Target>
<Actions>
<Action>
<ActionMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">read</AttributeValue>
<ActionAttributeDesignator DataType="http://www.w3.org/2001/XMLSchema#string" AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"/>
</ActionMatch>
</Action>
</Actions>
</Target>
<Condition>
<Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-is-in">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">developer</AttributeValue>
<SubjectAttributeDesignator DataType="http://www.w3.org/2001/XMLSchema#string"
AttributeId="urn:oasis:names:tc:xacml:2.0:subject:role" />
</Apply>
</Condition>
</Rule>
<Rule Effect="Deny" RuleId="DenyRule"/>
</Policy>

 

Точка реализации веб-политики (PEP)

 Основная задача PEP — перехватывать запросы к любым ресурсам, а затем создавать запрос XACML на основе атрибутов субъекта (субъект, обращающийся к ресурсу), действия, атрибутов ресурса и среды (время, дата, IP-адрес и т. Д.) И передать его PDP для принятия решения о доступе. Основываясь на решении PDP, PEP может разрешить доступ к ресурсу или нет.

package org.jboss.test.security.xacml.bindings.web;

import java.net.URI;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.jboss.security.xacml.core.model.context.ActionType;
import org.jboss.security.xacml.core.model.context.AttributeType;
import org.jboss.security.xacml.core.model.context.EnvironmentType;
import org.jboss.security.xacml.core.model.context.RequestType;
import org.jboss.security.xacml.core.model.context.ResourceType;
import org.jboss.security.xacml.core.model.context.SubjectType;
import org.jboss.security.xacml.factories.RequestAttributeFactory;
import org.jboss.security.xacml.factories.RequestResponseContextFactory;
import org.jboss.security.xacml.interfaces.RequestContext;

/**
* PEP for the web layer
* @author Anil Saldhana
*/
public class WebPEP
{
String ACTION_IDENTIFIER = "urn:oasis:names:tc:xacml:1.0:action:action-id";
String CURRENT_TIME_IDENTIFIER = "urn:oasis:names:tc:xacml:1.0:environment:current-time";
String RESOURCE_IDENTIFIER = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
String SUBJECT_IDENTIFIER = "urn:oasis:names:tc:xacml:1.0:subject:subject-id";
String SUBJECT_ROLE_IDENTIFIER = "urn:oasis:names:tc:xacml:2.0:subject:role";

@SuppressWarnings("unchecked")
public RequestContext createXACMLRequest(HttpServletRequest request,
Principal principal, Group roleGroup) throws Exception
{
RequestContext requestCtx = RequestResponseContextFactory.createRequestCtx();

//Create a subject type
SubjectType subject = new SubjectType();
subject.getAttribute().add(RequestAttributeFactory.createStringAttributeType(
SUBJECT_IDENTIFIER, "jboss.org", principal.getName()));
Enumeration roles = (Enumeration) roleGroup.members();
while(roles.hasMoreElements())
{
Principal rolePrincipal = roles.nextElement();
AttributeType attSubjectID = RequestAttributeFactory.createStringAttributeType(
SUBJECT_ROLE_IDENTIFIER, "jboss.org", rolePrincipal.getName());
subject.getAttribute().add(attSubjectID);
}

//Create a resource type
ResourceType resourceType = new ResourceType();
resourceType.getAttribute().add(RequestAttributeFactory.createAnyURIAttributeType(
RESOURCE_IDENTIFIER, null, new URI(request.getRequestURI())));

//Create an action type
ActionType actionType = new ActionType();
actionType.getAttribute().add(RequestAttributeFactory.createStringAttributeType(
ACTION_IDENTIFIER, "jboss.org", "read"));

//Create an Environment Type (Optional)
EnvironmentType environmentType = new EnvironmentType();
environmentType.getAttribute().add(RequestAttributeFactory.createDateTimeAttributeType(
CURRENT_TIME_IDENTIFIER, null));

//Create a Request Type
RequestType requestType = new RequestType();
requestType.getSubject().add(subject);
requestType.getResource().add(resourceType);
requestType.setAction(actionType);
requestType.setEnvironment(environmentType);

requestCtx.setRequest(requestType);

return requestCtx;
}
}

 

Этот PEP нуждается в небольшом изменении, когда вам нужно выяснить действие ресурса XACML («read», «Write») с помощью метода http — get или post.

actionType.getAttribute().add(RequestAttributeFactory.createStringAttributeType(
ACTION_IDENTIFIER, "jboss.org", "read"));

 

Модульный тест

Как веб-разработчик, вы должны создать фильтр сервлета для включения кода, который я показываю здесь, в качестве теста JUnit.

package org.jboss.test.security.xacml.bindings.web;



import java.io.InputStream;

import java.security.Principal;

import java.security.acl.Group;



import javax.servlet.http.HttpServletRequest;



import junit.framework.TestCase;



import org.jboss.security.xacml.core.JBossPDP;

import org.jboss.security.xacml.interfaces.PolicyDecisionPoint;

import org.jboss.security.xacml.interfaces.RequestContext;

import org.jboss.security.xacml.interfaces.XACMLConstants;

import org.jboss.test.security.xacml.factories.util.XACMLTestUtil;





/**

* Unit Tests for the Web bindings

*/

public class WebLayerUnitTestCase extends TestCase

{

//Ensure that a subject with the role of developer can access the resource
public void testWebBinding() throws Exception

{

PolicyDecisionPoint pdp = getPDP();

assertNotNull("JBossPDP is != null", pdp);



Principal p = new Principal()

{

public String getName()

{

return "testuser";

}

};



//Create Role Group

Group grp = XACMLTestUtil.getRoleGroup("developer");



String requestURI = "http://test/developer-guide.html";

HttpRequestUtil util = new HttpRequestUtil();

HttpServletRequest req = util.createRequest(p, requestURI);



//Check PERMIT condition

WebPEP pep = new WebPEP();

RequestContext request = pep.createXACMLRequest(req, p, grp);



assertEquals("Access Allowed?", XACMLConstants.DECISION_PERMIT, XACMLTestUtil.getDecision(pdp, request));

}



//Ensure that a subject with a role of "imposter" cannot access the resource
public void testNegativeAccessWebBinding() throws Exception

{

PolicyDecisionPoint pdp = getPDP();

assertNotNull("JBossPDP is != null", pdp);

Principal p = new Principal()

{

public String getName()

{

return "testuser";

}

};



//Create Role Group

Group grp = XACMLTestUtil.getRoleGroup("imposter");

String requestURI = "http://test/developer-guide.html";

HttpRequestUtil util = new HttpRequestUtil();

HttpServletRequest req = util.createRequest(p, requestURI);



//Check DENY condition

WebPEP pep = new WebPEP();

RequestContext request = pep.createXACMLRequest(req, p, grp);



assertEquals("Access Disallowed?", XACMLConstants.DECISION_DENY, XACMLTestUtil.getDecision(pdp, request));

}



private PolicyDecisionPoint getPDP()

{

ClassLoader tcl = Thread.currentThread().getContextClassLoader();

InputStream is = tcl.getResourceAsStream("test/config/webConfig.xml");

assertNotNull("InputStream != null", is);



return new JBossPDP(is);

}

}

 

HTTPRequestUtil — просто фиктивный класс утилит, который создает тестовый объект HttpServletRequest. Ваше
веб-приложение будет иметь доступ к объекту запроса из веб-контейнера.

 

Несмотря на то, что политика XACML довольно проста, вы должны иметь возможность вносить изменения в файл (ы) политики без изменения PEP или PDP.

 

Файл конфигурации JBossXACML

Если вы посмотрите на метод getPDP (), вы увидите ссылку на файл webConfig.xml. Это файл конфигурации,
используемый JBossXACML, чтобы указать, где расположены политики XACML.

 

<ns:jbosspdp xmlns:ns="urn:jboss:xacml:2.0">
<ns:Policies>
<ns:Policy>
<ns:Location>test/policies/bindings/web/web-policy.xml</ns:Location>
</ns:Policy>
</ns:Policies>
<ns:Locators>
<ns:Locator Name="org.jboss.security.xacml.locators.JBossPolicyLocator">
</ns:Locator>
</ns:Locators>
</ns:jbosspdp>

 

Вывод

В этой статье мы увидели реализацию детального механизма авторизации с использованием XACML.

 

Рекомендации

XACML в Википедии: http://en.wikipedia.org/wiki/XACML
JBossXACML: https://www.jboss.org/community/docs/DOC-10840

Руководство пользователя: http://www.jboss.org/file -доступ / по умолчанию / Участники / jbosssecurity / Freezone / релизы / jbossxacml / 2.0.2.GA / руководство / html / jbossxacml.html
 

Об авторе:

Анил Салдхана — ведущий архитектор безопасности в JBoss. Он ведет блог на http://anil-identity.blogspot.com