На самом деле я столкнулся с проблемой распространения ролей, и мне нужна помощь. Я использую Glassfish 4.0 и развертываю войну, содержащую JAX-RS
ресурс и EJB
с удаленным и локальным представлением для целей тестирования.
Я объявил роли в своих дескрипторах развертывания web.xml
и glassfish-web.xml
, связанных с файловой областью в Glassfish. Эти роли правильно используются ресурсом JAX-RS
, но EJB
, похоже, их не видит.
Я покажу вам файлы, которые я использую, а затем результаты различных выходов вызовов, которые я тестировал до сих пор.
TL/DR: извините за очень длинный пост. Пожалуйста, перейдите к ЧАСТИ II / Тесту 2
ЧАСТЬ I: Код
Дескриптор развертывания glassfish-web.xml
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
<context-root>/war-test-4</context-root>
<security-role-mapping>
<role-name>test</role-name>
<group-name>test</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>test2</role-name>
<group-name>test2</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>authenticated</role-name>
<group-name>authenticated</group-name>
</security-role-mapping>
</glassfish-web-app>
Дескриптор развертывания web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>war-test-4</display-name>
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
<security-role-ref>
<description>Test</description>
<role-name>test</role-name>
<role-link>test</role-link>
</security-role-ref>
<security-role-ref>
<description>Auth users</description>
<role-name>authenticated</role-name>
<role-link>authenticated</role-link>
</security-role-ref>
<security-role-ref>
<description>Test2</description>
<role-name>test2</role-name>
<role-link>test2</role-link>
</security-role-ref>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin Resources</web-resource-name>
<description>Administration resources</description>
<url-pattern>/jaxrs/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<description>TEST</description>
<role-name>test</role-name>
<role-name>test2</role-name>
<role-name>authenticated</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>test-realm</realm-name>
</login-config>
<security-role>
<description>Test</description>
<role-name>test</role-name>
</security-role>
<security-role>
<description>Auth users</description>
<role-name>authenticated</role-name>
</security-role>
<security-role>
<description>Test2</description>
<role-name>test2</role-name>
</security-role>
</web-app>
EJB без сохранения состояния SessionBeanTest.java
/**
* Session Bean implementation class SessionBeanTest
*/
@Stateless(mappedName = "SessionBeanTest")
//@RolesAllowed({"authenticated"})
//@DeclareRoles({"authenticated","test","test2"})
public class SessionBeanTest implements SessionBeanRemote, SessionBeanLocal {
@Resource
private SessionContext sessionContext;
@Override
public String get() {
return MessageFormat
.format("EJB Call by :{0} authenticated? : {1} / test2 ? : {2} / test ? : {3}",
sessionContext.getCallerPrincipal().getName(),
sessionContext.isCallerInRole("authenticated"),
sessionContext.isCallerInRole("test2"), sessionContext.isCallerInRole("test"));
}
}
Моя служба JAX-RS AccessTest.java
@Path("access")
//@DeclareRoles({/*"authenticated","test",*/"test2"})
@Stateless
public class AccessTest {
@Inject
private SessionBeanLocal testBean;
@GET
@Path("1")
public Response test(@Context HttpServletRequest req){
return Response.ok(MessageFormat
.format("JAX-RS Call by :{0} authenticated? : {1} / test2 ? : {2} / test ? : {3}",
req.getUserPrincipal().getName(),
req.isUserInRole("authenticated"),
req.isUserInRole("test2"),
req.isUserInRole("test"))).build();
}
@GET
@Path("2")
public Response test2(){
return Response.ok(testBean.get()).build();
}
}
Как вы, наверное, заметили, я прокомментировал аннотации @DeclareRoles
и @RolesAllowed
как в моем EJB, так и в моем ресурсе JAX-RS. У меня также есть 2 URI в моей службе JAX-RS. Один напрямую предоставляет пользователю информацию и роли, а другой использует EJB для получения той же информации. Оба должны возвращать один и тот же результат, если пользователь вошел в систему.
ЧАСТЬ II: Тесты
Теперь, используя тестер веб-сервиса (Paw на Mac, на основе Curl, очень полезно!), я получаю доступ к обоим URI:
Тест 1: Ни один пользователь не вошел в систему
Вывод для URI /jaxrs/access/1
без пользователя
HTTP/1.1 401 Unauthorized
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
Вывод для URI /jaxrs/access/2
без пользователя
HTTP/1.1 401 Unauthorized
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
Пока вроде работает по плану, для доступа к ресурсу требуется аутентифицированный пользователь. Но взгляните на второй тест...
Тест 2: пользователь со всеми ролями вошел в систему
Вывод для URI /jaxrs/access/1
со всеми ролями пользователя
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
JAX-RS Call by :testadmin authenticated? : true / test2 ? : true / test ? : true
Вывод для URI /jaxrs/access/2
со всеми ролями пользователя
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
EJB Call by :testadmin authenticated? : **false** / test2 ? : **false** / test ? : **false**
Это та часть, которую я не понимаю. Роли, объявленные в web.xml
и glassfish-web.xml
, не распространяются на EJB, который находится в том же проекте WAR.
Тест 3: раскомментирование аннотации @DeclareRoles
в коде
Независимо от того, раскомментирую ли я @DeclareRoles({"authenticated"})
в своем EJB или в моей службе JAX-RS, я получаю следующий вывод:
Вывод для URI /jaxrs/access/1
со всеми ролями пользователя, @DeclareRoles
без комментариев
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
JAX-RS Call by :testadmin authenticated? : true / test2 ? : true / test ? : true
Вывод для URI /jaxrs/access/2
со всеми ролями пользователя, @DeclareRoles
без комментариев
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
EJB Call by :testadmin authenticated? : **true** / test2 ? : **false** / test ? : **false**
Только те роли, которые я объявляю, видны EJB, но служба JAX-RS видит их все
ЧАСТЬ III: Удаленный вызов EJB
У меня также есть чистый Java-клиент для тестирования. Вот :
public class Main {
public static void main(String[] args) throws Exception {
getRemoteService();
}
public static void getRemoteService() throws Exception {
String host = "127.0.0.1";
String port = "3700";
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state", "com.sun.cobra.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
props.setProperty("org.omg.CORBA.ORBInitialHost", host);
props.setProperty("org.omg.CORBA.ORBInitialPort", port);
Context amInitial = null;
amInitial = new InitialContext(props);
ProgrammaticLogin programmaticLogin = new ProgrammaticLogin();
programmaticLogin.login("testuser2", "password");
SessionBeanRemote service = (SessionBeanRemote) amInitial.lookup("SessionBeanTest");
System.out.println(service.get());
programmaticLogin.logout();
programmaticLogin.login("testadmin", "password");
System.out.println(service.get());
}
}
Этот клиент использует интерфейс ProgrammaticLogin
для входа в систему и использования EJB с CORBA. Я не планирую использовать его, кроме как для тестирования.
Сначала клиент войдет под пользователем с ограниченными правами, затем под пользователем со всеми ролями. Вот результаты теста с использованием этого клиента:
Тест 1: Тестирование удаленного EJB с комментарием @DeclareRoles
EJB Call by :ANONYMOUS authenticated? : false / test2 ? : false / test ? : false
EJB Call by :ANONYMOUS authenticated? : false / test2 ? : false / test ? : false
Тест 2: Тестирование удаленного EJB с раскомментированным @DeclareRoles({"authenticated","test","test2"})
EJB Call by :ANONYMOUS authenticated? : false / test2 ? : false / test ? : false
EJB Call by :ANONYMOUS authenticated? : false / test2 ? : false / test ? : false
Здесь пользователи также не аутентифицированы. Но когда я добавляю аннотацию @RolesAllowed
к EJB, я получаю следующее:
Тест 3: Тестирование удаленного EJB с добавленными @DeclareRoles
и @RolesAllowed({"authenticated"})
EJB Call by :testuser2 authenticated? : true / test2 ? : true / test ? : false
EJB Call by :testadmin authenticated? : true / test2 ? : true / test ? : true
Это все, что я тестировал до сих пор. Я не понимаю, почему роли, объявленные в дескрипторах развертывания, правильно используются службой JAX-RS, но не компонентом Stateless EJB. Мне нужна ваша помощь в этом, я на самом деле не помещаю стандартные аннотации ролей в каждый EJB.