Tomcat JMX连接 - 认证失败

4

我在设置Tomcat的JMX时遇到了一些问题。我添加了以下属性:

  CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070      -Dcom.sun.management.jmxremote.password.file=$CATALINA_BASE/conf/jmxremote.password      -Dcom.sun
    .management.jmxremote.ssl=false"

我已经将jmxremote.password文件添加到conf目录中。我编写了一个客户端工具,可以连接到运行在18070端口上的JMX服务器。当我运行客户端程序时,会出现以下错误。

    Exception in thread "main" java.lang.SecurityException: Authentication failed! Credentials required
       at com.sun.jmx.remote.security.JMXPluggableAuthenticator.authenticationFailure(JMXPluggableAuthenticator.java:193)
       at com.sun.jmx.remote.security.JMXPluggableAuthenticator.authenticate(JMXPluggableAuthenticator.java:145)
       at sun.management.jmxremote.ConnectorBootstrap$AccessFileCheckerAuthenticator.authenticate(ConnectorBootstrap.java:185)
       at javax.management.remote.rmi.RMIServerImpl.doNewClient(RMIServerImpl.java:213)
       at javax.management.remote.rmi.RMIServerImpl.newClient(RMIServerImpl.java:180)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
       at sun.rmi.transport.Transport$1.run(Transport.java:159)
       at java.security.AccessController.doPrivileged(Native Method)
       at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
       at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
       at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
       at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
       at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
       at java.lang.Thread.run(Thread.java:619)
       at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
       at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
       at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
       at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
       at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2312)
       at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:277)
       at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
       at com.bt.c21sc.c21tkprobe.accessors.C21TkProbeJmxDAO.connect(Unknown Source)
       at com.bt.c21sc.c21tkprobe.service.C21TkProbeBD.execute(Unknown Source)
       at com.bt.c21sc.c21tkprobe.C21AppserverProbe.main(Unknown Source)

如果我更改CATALINA_OPTS属性为
CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070 -Dcom.sun.management.jmxremote.password.file=$CATALINA_BASE/conf/jmxremote.password -Dcom.sun
.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"

然后它很好地工作了。我想我困惑的是什么被归类为远程访问。我正在Tomcat实例之外运行客户端程序,但Tomcat和客户端工具都在同一台机器上(即不同的虚拟机但相同的环境)。我认为如果我从不同的机器远程访问JMX服务器,我必须配置远程身份验证。

通过远程访问,他们是否意味着可以从任何VM(本地或远程)访问JMX服务器?

编辑

谢谢。我发现问题是即使我在jmxremort.password和jmxremote.access文件中提供了用户名和密码,我仍然必须从客户端提供用户名和密码。

您说得对,如果在本地运行,我不必提供用户凭据。我已经证明了这一点,因为我可以通过Jconsole访问Tomcat的JVM。

我正在以编程方式访问它,因此必须提供下面显示的URL service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi

然后我就可以像下面显示的那样获取JMX服务器。

url = new JMXServiceURL(urlString);         
Hashtable<String, String[]> env = new Hashtable<String, String[]>();
String[] credentials = new String[] {user,pass};
env.put(JMXConnector.CREDENTIALS, credentials);         
jmxc = JMXConnectorFactory.connect(url,env); 
mbsc = jmxc.getMBeanServerConnection(); 

如果我在本地访问,该怎么做?我知道如果没有用户凭证,它在本地不起作用,因为这就是我需要提供凭证的原因。如果Jconsole或visualvm可以连接到它,那么必须有一种不同的方法允许检索Tomcat jmx服务器而无需提供端口号。
URL包括端口号。如果我以编程方式访问JMX服务器,如何访问它而无需指定端口号?
顺便说一下,我正在使用Tomcat 5.5和JDK 1.6
谢谢

重复 - 你能压缩这些请求吗? - mtraut
我发现问题在于,尽管我在jmxremote.password和jmxremote.access文件中提供了用户名和密码,但我仍然需要从客户端提供用户名和密码。当然,jmxremote.access充当密码存储库,因此您必须使用JMX客户端进行身份验证。 - davorp
1个回答

3

远程访问

远程访问指从另一台机器访问,通过另一个虚拟机本地访问,您无需设置JMX[注1]。您可以尝试在没有JMX的情况下启动Java应用程序,然后在同一台机器上启动VisualVM。启动的应用程序应该出现在“本地”(在VisualVM中)。

正如异常所述:Authentication failed! Credentials required 您是否提供了用户名和密码?;) 我猜您已经提供了...

可能的解决方案

如果您已经提供了用户名和密码,则应尝试从CATALINA_OPTS中删除$CATALINA_BASE并输入硬编码值,以查看这是否是根本问题。

例如:

CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070 -Dcom.sun.management.jmxremote.password.file=/opt/tomcat6/conf/jmxremote.password -Dcom.sun.management.jmxremote.ssl=false"

如果可以工作,则尝试像这样:

CATALINA_OPTS="-Dcom.sun.management.jmxremote.port=18070
-Dcom.sun.management.jmxremote.password.file=`echo $CATALINA_BASE`/conf/jmxremote.password
-Dcom.sun.management.jmxremote.ssl=false"

[note 1]: 这里说明:"在早期版本的Java SE平台中,为了允许JMX客户端访问本地Java VM,您必须在启动Java VM或Java应用程序时设置以下系统属性(com.sun.management.jmxremote)。 设置此属性将注册Java VM平台的MBeans并通过私有接口发布远程方法调用(RMI)连接器,以允许JMX客户端应用程序监视本地Java平台,即在与JMX客户端运行在同一台计算机上的Java VM。 在Java SE 6平台中,不再需要设置此系统属性。 在Java SE 6平台上启动的任何应用程序都将支持Attach API,因此在需要时将自动可用于本地监视和管理。"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接