【发布时间】:2015-06-17 21:57:35
【问题描述】:
我实际上遇到了角色传播问题,我需要帮助。
我正在使用 Glassfish 4.0,并且我正在部署一个包含 JAX-RS 资源和带有远程和本地视图的 EJB 的战争,用于测试目的。
我已在我的 web.xml 和 glassfish-web.xml 部署描述符中声明了角色,这些角色链接到 Glassfish 中的文件领域。
JAX-RS 资源正确使用了这些角色,但 EJB 似乎看不到它们。
我将向您展示我正在使用的文件,然后是我迄今为止测试过的不同调用输出的结果。
TL/DR:很抱歉这篇文章太长了。请转到第二部分/测试 2
第一部分:代码
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();
}
}
您可能已经注意到,我在 EJB 和 JAX-RS 资源中都注释了 @DeclareRoles 和 @RolesAllowed。 我的 JAX-RS 服务中还有 2 个 URI .一种是直接给用户信息和角色,另一种是使用 EJB 来检索相同的信息。 如果用户登录,两者都应该返回完全相同的输出。
第二部分:测试
现在,使用网络服务测试器(Mac 上的 Paw,基于 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 中声明的角色不会传播到同一个WAR 项目中的EJB。
测试 3:取消注释代码中的 @DeclareRoles 注释
无论我在 EJB 还是 JAX-RS 服务中取消注释 @DeclareRoles({"authenticated"}),我都会得到以下输出:
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 服务可以看到所有角色
第三部分:远程 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 接口登录并使用带有CORBA 的EJB。除了测试之外,我不打算使用它。
首先,客户端将使用受限用户登录,然后使用具有所有角色的用户登录。 以下是使用此客户端的测试结果:
测试 1 : 用 @DeclareRoles 注释测试远程 EJB
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
在这里,用户也没有经过身份验证。但是当我向 EJB 添加 @RolesAllowed 注释时,我得到了这个:
测试 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 服务正确使用了部署描述符中声明的角色,但无状态 EJB 却没有。在这方面我需要你的帮助,我不太愿意在每个 EJB 上添加样板角色注释。
【问题讨论】:
-
嗨@mrik974,您找到任何解决角色传播和匿名问题的方法了吗?
-
不,它仍然让我很烦。我必须继续前进,但如果有人找到解决方案,我将非常乐意尝试。
-
这太令人沮丧了,根本没有任何帮助。我在网上找到的所有此类问题都没有答案:(
-
大家好,你们有什么解决办法吗? GlassFish 4.1 也有同样的问题。我什至尝试添加 glassfish-ejb-jar.xml,但它也没有帮助。
标签: glassfish ejb ejb-3.1 glassfish-4