我有一个客户端应用程序,它作为 Apache Tomcat 上的 Servlet 运行,连接到 WildFly 10.1 或 WebLogic 12c 应用程序服务器。该应用程序最近从 JBoss 6.1 和 WebLogic 11g 移植到这些较新的应用程序服务器上。使用 WildFly 10.1 时,应用程序按预期工作,但当它尝试与 WebLogic 12c 上运行的主应用程序通信时,我不断收到“用户没有足够的权限访问 EJB”。
我确实遇到过关于 JNDI 上下文和线程的 Oracle 引用资料,其中提到用户与线程相关联,而另一份引用资料则提到 WebLogic 9.0 中的行为发生了变化,删除了 支持虚拟机范围内的默认用户,并且您必须位于同一线程(或子线程)中才能使身份验证正常工作。
我能够编写一个简单的测试客户端来确认此行为。如果我在一个线程中实例化 InitialContext,但随后尝试在另一个线程中使用它,则会收到“User”错误。如果我再试一次,但这次在主应用程序中实例化 InitialContext,我就能够通过主应用程序以及我创建的任何其他线程成功与应用程序服务器进行通信。
这是复制错误的示例测试客户端:
import java.text.SimpleDateFormat;
import java.util.Properties;
import javax.ejb.FinderException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.supportsoft.encore.inventory.dto.DeviceDTO;
import com.supportsoft.encore.inventory.ejb.InventoryInterfaceFactory;
import com.supportsoft.encore.inventory.ejb.remote.DeviceManager;
import com.supportsoft.encore.system.exception.RealmViolationException;
public class GetInitialContextThreaded {
private static InitialContext ic;
public static void main(String[] args) {
try {
// Use a thread to initialize the initial context
Thread thread1 = new Thread() {
public void run() {
log("THREAD1: Getting InitialContext.");
Properties icProps = new Properties();
icProps.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
icProps.put(Context.PROVIDER_URL, "t3://localhost:6002");
// icProps.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
// icProps.put(Context.PROVIDER_URL, "http-remoting://localhost:7777");
icProps.put(Context.SECURITY_PRINCIPAL, "system");
icProps.put(Context.SECURITY_CREDENTIALS, "system");
// icProps.put("jboss.naming.client.ejb.context", false);
// icProps.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
// icProps.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
// icProps.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
icProps.put("java.naming.factory.url.pkgs", "weblogic.jndi.factories:weblogic.corba.j2ee.naming.url");
// icProps.put("weblogic.jndi.enableDefaultUser", "true");
try {
ic = new InitialContext(icProps);
log("THREAD1: Have InitialContext.");
} catch (NamingException e) {
e.printStackTrace();
}
}
};
thread1.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// Test connection
log("MAIN: Testing connection to app server.");
InventoryInterfaceFactory iFactory = getInventoryInterfaceFactory(ic, "MAIN");
log("MAIN: Getting DeviceManager handle");
DeviceManager devMgr = iFactory.getDeviceManager();
log("MAIN: Have DeviceManager handle");
log("MAIN: Get device");
DeviceDTO device = devMgr.getByID(1000L);
log("MAIN: Have device");
Thread thread2 = new Thread() {
public void run() {
log("THREAD2: Testing connection to app server.");
InventoryInterfaceFactory iFactory = getInventoryInterfaceFactory(ic, "THREAD2");
try {
log("THREAD2: Getting DeviceManager handle");
DeviceManager devMgr = iFactory.getDeviceManager();
log("THREAD2: Have DeviceManager handle");
log("THREAD2: Get device");
DeviceDTO device = devMgr.getByID(1000L);
log("THREAD2: Have device");
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread2.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log("MAIN: Successfully connected to app server.");
} catch (NamingException e) {
e.printStackTrace();
} catch (FinderException e) {
e.printStackTrace();
} catch (RealmViolationException e) {
e.printStackTrace();
}
}
private static InventoryInterfaceFactory getInventoryInterfaceFactory(InitialContext ctx, String logPrefix) {
InventoryInterfaceFactory factory = null;
try {
log(logPrefix + ": Instantiating factory");
factory = InventoryInterfaceFactory.getInstance(ctx);
log(logPrefix + ": Instantiated factory");
} catch (NamingException e) {
e.printStackTrace();
}
return factory;
}
private static void log(String message) {
SimpleDateFormat time_formatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS z yyyy");
String current_time_str = time_formatter.format(System.currentTimeMillis());
System.out.println(current_time_str + ": " + message);
}
}
这是我运行它时看到的输出:
Tue Oct 22 15:34:35.395 ADT 2019: THREAD1: Getting InitialContext.
Tue Oct 22 15:34:37.469 ADT 2019: THREAD1: Have InitialContext.
Tue Oct 22 15:34:40.371 ADT 2019: MAIN: Testing connection to app server.
Tue Oct 22 15:34:40.372 ADT 2019: MAIN: Instantiating factory
Tue Oct 22 15:34:40.401 ADT 2019: MAIN: Instantiated factory
Tue Oct 22 15:34:40.402 ADT 2019: MAIN: Getting DeviceManager handle
Tue Oct 22 15:34:40.580 ADT 2019: MAIN: Have DeviceManager handle
Tue Oct 22 15:34:40.580 ADT 2019: MAIN: Get device
Exception in thread "main" javax.ejb.EJBAccessException: [EJB:010160]Security violation: User <anonymous> has insufficient permission to access EJB type=<ejb>, application=xyz, module=xyz-impl.jar, ejb=XYZManagerBean, method=getByID, methodInterface=Remote, signature={java.lang.Long}.
at weblogic.utils.StackTraceDisabled.unknownMethod()
正如我上面提到的,通过让主应用程序实例化 InitialContext,在我的测试客户端中解决这个问题相当简单。
我的问题是如何在 Apache Tomcat 上部署和运行的 servlet 中处理这个问题。当应用程序启动时,initialize() 方法会执行许多操作,例如加载属性文件、实例化 InitialContext 以及测试与应用程序服务器的连接。一切都很好。问题是当 servlet 开始处理新请求并尝试与 WebLogic 12c 应用程序服务器通信时。正是在这一点上,我收到了“用户”错误。
有没有办法配置 Tomcat 或 servlet,以便可以在 servlet 线程之间共享 InitialContext,而不会“丢失”经过身份验证的主体?在 WebLogic 11g 中,我们包含了一个名为“weblogic.jndi.enableDefaultUser”的上下文属性,并将其设置为“true”,但这在 WebLogic 12c 中似乎不受支持。
有什么想法吗?
最佳答案
尝试回答,因为这对于寻找答案的人可能有用。
您是否在服务器启动时发现此问题发生? 如果是,请在Weblogic描述 rune 件中传递Principle名称
仅用于前
XXX.YYYY.CREATE.PRINCIPAL
关于java - 即使在 InitialContext 中指定了正确的用户,如何解析 'User <anonymous> has insufficient permission to access EJB',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58510531/