Artemis Origin Null Is Not Allowed to Call This Agent
Artemis Origin Null Is Not Allowed to Call This Agent⌗
解决不能访问jolokia http interface 接口的问题,访问报403 状态错误⌗
工作项目中需要使用到mq的消息管理api,如需要查询在线连接数,需要查看某一个clientId是否在线,需要整合到自身业务当中去,
对于artemis 就是一个黑盒,虽然是开源的,而且是完全开放的源代码,没有必须去改里面源码达到需求,其实artemis 后台提供了
丰富的http rest 接口。再比如根据某一个clientId 踢下线,超时设置,连接数查看,系统资源统计监控查询这些api 都是开放的
但发现实际使用过程中,并不是很顺利,踩了一些坑,标题就是常见的问题之一
比如官方这篇文档有提到通过 jolokia 提供 接口对外暴露调用,以一下是连接地址
Management · ActiveMQ Artemis Documentation (apache.org)
Exposing JMX using Jolokia
The default Broker configuration ships with the Jolokia HTTP agent deployed as a web application. Jolokia is a remote JMX-over-HTTP bridge that exposes MBeans. For a full guide as to how to use it refer to Jolokia Documentation, however a simple example to query the broker's version would be to use a browser and go to the URL http://username:password@localhost:8161/console/jolokia/read/org.apache.activemq.artemis:broker="0.0.0.0"/Version.
This would give you back something like the following:
{"request":{"mbean":"org.apache.activemq.artemis:broker=\"0.0.0.0\"","attribute":"Version","type":"read"},"value":"2.0.0-SNAPSHOT","timestamp":1487017918,"status":200}
访问格式如下,比如查询borker 版本
http://username:password@localhost:8161/console/jolokia/read/org.apache.activemq.artemis:broker="0.0.0.0"/Version
但实际过程就是报错如下 ,常见403错误
原因是 origin 这个参数是null, 官方也没有说清 origin 这个参数是怎么传过去,虽然做为开发对http接口协议还是有一点了解,
origin 这个参数就是需要指明访问目标。通常在http header头 加上即可
{
"error_type": "java.lang.Exception",
"error": "java.lang.Exception : Origin null is not allowed to call this agent",
"status": 403
}
加上后果然访问正常了
但在实际springboot 项目中,我们用restTemplate 这个http client 客户端,发现不行,还是403
postman 是可以的,我们在spring boot 项目中,用restTemplate 访问不行。为什么,后面我们没有绕过这个问题,没有换过库
没有使用postman 推荐的code ,以下是postman 推荐的,但没有尝试,我们还是坚持采用 restTemplate 客户端
Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.get("http://admin:[email protected]:8161/console/jolokia/")
.header("Origin", " http://172.20.151.90:8161")
.header("Content-Type", "application/json")
.body("{\"type\":\"exec\",\"mbean\":\"org.apache.activemq.artemis:broker=\\\"d2403827fe6c\\\"\",\"operation\":\"listConsumers(java.lang.String, int, int)\",\"arguments\":[\"{\\\"field\\\":\\\"CLIENT_ID\\\",\\\"operation\\\":\\\"EQUALS\\\",\\\"value\\\":\\\"86303335\\\",\\\"sortOrder\\\":\\\"asc\\\",\\\"sortColumn\\\":\\\"id\\\"}\",1,10]}")
.asString();
怀疑 restTemplate 并没有把orgin传过去,经过抓包 才发现
于是我们用wireshark
工具抓包发现restTemplate 没有把orgin 参数传给atemis-server
然后在百度一下,发现以下csdn 博客解决了,增加一行配置即可
System.setProperty("sun.net.http.allowRestrictedHeaders","true");
@Component
public class ArtemisJmxHelper {
@Autowired
private RestTemplate restTemplate;
private final String username="admin";
private final String password="admin";
public Map getTopicCosumer(String topic){
//这一行必须要加,才能让restTemplate 生效orgin参数
System.setProperty("sun.net.http.allowRestrictedHeaders","true");
// String url="http://admin:[email protected]:8161/console/jolokia";
String url="http://172.20.151.90:8161/console/jolokia/";
JolokiaReq jolokiaReq = new JolokiaReq();
jolokiaReq.setType("exec");
jolokiaReq.setOperation("listConsumers(java.lang.String, int, int)");
jolokiaReq.setMbean("org.apache.activemq.artemis:broker=\"d2403827fe6c\"");
Map req = new HashMap();
req.put("field","CLIENT_ID");
req.put("operation","EQUALS");
req.put("value","deviceClient");
req.put("sortOrder","asc");
req.put("sortColumn","id");
Object[] arguments=new Object[]{JSON.toJSONString(req),1,10};
jolokiaReq.setArguments(arguments);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.add("Origin","http://172.20.151.90:8161");
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
httpHeaders.add("Authorization", "Basic " + new String(encodedAuth));
HttpEntity httpEntity = new HttpEntity(jolokiaReq,httpHeaders);
String str = JSON.toJSONString(httpEntity);
System.out.println(str);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, str, String.class);
String body = responseEntity.getBody();
return null;
}
}
加了后 System.setProperty("sun.net.http.allowRestrictedHeaders","true");
403问题 最后总结一下:
有两点需要注意的,
第一,请求时,需要加用户名和密码,在header头增加orgin参数
第二,需要在jolokia-access.xml设置给一下跨域访问为 cors *//*