我们有 2 个 Java 应用程序通过 EJB 在 2 个不同的服务器上相互通信。
EJB 是在 Spring 中定义的,将 ejb 名称设置为 Web 逻辑中的外部 JNDI。
<bean id="codingRemote" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myEjb" />
<property name="businessInterface" value="com.my.ej.binterface" />
<property name="refreshHomeOnConnectFailure" value="true" />
</bean>
我将 refreshHomeOnConnectFailure 设置为 true,我可以重新启动远程服务器并重新连接,但问题是如果我重新部署到远程服务器(我们的部署过程完全删除了 Web 逻辑域,重新创建它并部署新的工件)它似乎尝试连接但存在安全问题。
在远程机器上,我在“重新部署”过程之后收到以下异常,并且从客户端进行了调用 - 因此客户端正在尝试进行调用,但远程机器/JVM 不接受调用:
<Aug 28, 2014 11:20:23 AM CAT> <Warning> <RMI> <WL-080003> <A RuntimeException was generated by the RMI server: weblogic.jndi.internal.AdminRoleBasedDispatchServerRef@9, implementation: 'weblogic.jndi.internal.RootNamingNode@ac24b13', oid: '9', implementationClassName: 'weblogic.jndi.internal.RootNamingNode'
java.lang.SecurityException: [Security:090398]Invalid Subject: principals=[weblogic, Administrators].
java.lang.SecurityException: [Security:090398]Invalid Subject: principals=[weblogic, Administrators]
at weblogic.security.service.SecurityServiceManager.seal(SecurityServiceManager.java:833)
at weblogic.security.service.SecurityServiceManager.getSealedSubjectFromWire(SecurityServiceManager.java:522)
at weblogic.rjvm.MsgAbbrevInputStream.getSubject(MsgAbbrevInputStream.java:355)
at weblogic.rmi.internal.BasicServerRef.acceptRequest(BasicServerRef.java:1022)
at weblogic.rmi.internal.BasicServerRef.dispatch(BasicServerRef.java:350)
Truncated. see log file for complete stacktrace
环境Java7/Weblogic12/Spring2.5
知道如何通过这个以允许重新登录或用户凭据登录吗?
----------
我找到了 2 种可能的解决方案,但我不完全确定哪一种是最好使用的,以及这样做是否有任何问题。
解决方案 1: - 指定一个 JNDI 模板,但这样做违背了在 weblogic 中定义它的目的,现在它本身就是应用程序的一部分。
<bean id="codingRemote" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myEjb" />
<property name="businessInterface" value="com.my.ej.binterface" />
<property name="refreshHomeOnConnectFailure" value="true" />
<property name="jndiTemplate">
<ref local="myProcessJndiTemplate" />
</property>
</bean>
<bean id="myProcessJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${specify.the.context}</prop>
<prop key="java.naming.provider.url">${specify.the.url}</prop>
<prop key="java.naming.security.authentication">none</prop>
</props>
</property>
</bean>
解决方案2: - 我在这个站点上发现,如果我们重写 SimpleRemoteStatelessSessionProxyFactoryBean,我们可以再次实例化安全性。
public class WebLogicSimpleRemoteStatelessSessionProxyFactoryBean extends SimpleRemoteStatelessSessionProxyFactoryBean {
@Override protected Object create() throws NamingException, InvocationTargetException {
try {
return getJndiTemplate().execute(new JndiCallback() {
public Object doInContext(final Context context) throws NamingException {
try {
return WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.create();
} catch (final InvocationTargetException ite) {
throw new RuntimeException(ite);
}
}
});
} catch (final RuntimeException re) {
throw (InvocationTargetException) re.getCause();
}
}
protected void removeSessionBeanInstance(final EJBObject ejbObject) {
try {
getJndiTemplate().execute(new JndiCallback() {
public Object doInContext(final Context context) throws NamingException {
WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.removeSessionBeanInstance(ejbObject);
return null;
}
});
} catch (final NamingException e) {
throw new RuntimeException(e);
}
}
protected Object doInvoke(final MethodInvocation methodInvocation) throws Throwable {
try {
return getJndiTemplate().execute(new JndiCallback() {
public Object doInContext(final Context context) throws NamingException {
try {
return WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.doInvoke(methodInvocation);
} catch (final Throwable t) {
if (t instanceof NamingException) {
throw (NamingException) t;
} else {
throw new RuntimeException(t);
}
}
}
});
} catch (final RuntimeException re) {
throw re.getCause();
}
}
}