向 CometD 订阅消息添加自定义字段
Add custom fields to CometD subscribe message
我在 Android 上使用 CometD Java 客户端。
compile group: 'org.cometd.java', name: 'cometd-java-client', version:
'2.9.1'
我需要订阅 CometD 服务器上的频道。但是有一个问题 - 服务器需要自定义订阅消息(这是来自服务器文档的预期订阅消息有效负载):
[
{
"user": "xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
"domain": "xyz",
"pid": "gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10",
"sid": "85f103a2",
"gid": "WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o",
"pageId": "6ea23e",
"entityId": "xyz",
"triggeringGoal": "3E955818355C44E2479B2A26629E69566C8C6376",
"chatSearchPattern": "ua.domain=xyz",
"startTime": 1482931626853,
"metadata": "{}",
"chatMetadata": "{}",
"language": "en",
"id": "3",
"channel": "\/meta\/subscribe",
"subscription": "\/chat\/xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
"clientId": "26l1v2ngpdcwdtno1wu30rk92dur4",
"ext": {
}
}
]
所以我的问题是如何向订阅消息添加自定义字段(user
、domain
、pid
、sid
等)?目前我正在订阅这样的频道:
cometdClient.getChannel("/chat/" + clientID).subscribe(new ChannelListener("/chat/ messages"), new ChannelListener("/chat/ progress"));
但它如预期的那样失败了。
顺便说一句,我使用 org.eclipse.jetty.client.HttpClient
作为 HttpClient。
首先,你真的应该升级,因为 CometD 2.9.1 现在真的很旧,JDK 7 在 Android 上受支持。
要求 /meta/subscribe
消息中包含所有这些字段的服务器设计确实是错误的。
大多数信息是静态的(例如 user
和各种 "cookies" 例如 pid
等)并且可以在 CometD 握手时确定,因此不需要发送它在订阅期间结束。
此外,在 /meta/subscribe
消息中发送它会使其受到攻击(例如,攻击者可以伪造具有不同 user
字段的消息)。你想阅读 security section of the CometD documentation.
此外,不推荐为每个用户使用一个频道(因为频道名称似乎是 /chat/
和 user
字段的串联),因为它可能会创建一个很多频道,而使用单个服务频道(并且 user
作为正在发送的消息的字段)可以更有效地实现相同的功能。
如果您真的必须将这些字段添加到 /meta/subscribe
消息中,方法是使用 custom extension,按照这些行:
class SubscribeExtension extends ClientSession.Extension.Adapter {
@Override
public boolean sendMeta(ClientSession session, Message.Mutable message) {
if (Channel.META_SUBSCRIBE.equals(message.getChannel())) {
String subscription = (String)message.get(Message.SUBSCRIPTION_FIELD);
if (subscription.startsWith("/chat/") {
// Add fields.
}
}
return true;
}
}
最后,如果您确实需要向 /meta/subscribe
消息添加额外的字段,您希望在 ext
字段中使用适当的命名空间进行操作:
{
"id": "3",
"channel": "/meta/subscribe",
"subscription": "/chat/xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
"clientId": "26l1v2ngpdcwdtno1wu30rk92dur4",
"ext": {
"com.acme.myapp": {
"time": 1234567890,
"pageId": "6ea23e",
...
}
}
}
请注意额外的字段如何不会污染消息本身,而是分组在命名空间 com.acme.app
下的 ext
字段中,这将代表您的公司和应用程序。
我在 Android 上使用 CometD Java 客户端。
compile group: 'org.cometd.java', name: 'cometd-java-client', version: '2.9.1'
我需要订阅 CometD 服务器上的频道。但是有一个问题 - 服务器需要自定义订阅消息(这是来自服务器文档的预期订阅消息有效负载):
[
{
"user": "xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
"domain": "xyz",
"pid": "gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10",
"sid": "85f103a2",
"gid": "WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o",
"pageId": "6ea23e",
"entityId": "xyz",
"triggeringGoal": "3E955818355C44E2479B2A26629E69566C8C6376",
"chatSearchPattern": "ua.domain=xyz",
"startTime": 1482931626853,
"metadata": "{}",
"chatMetadata": "{}",
"language": "en",
"id": "3",
"channel": "\/meta\/subscribe",
"subscription": "\/chat\/xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
"clientId": "26l1v2ngpdcwdtno1wu30rk92dur4",
"ext": {
}
}
]
所以我的问题是如何向订阅消息添加自定义字段(user
、domain
、pid
、sid
等)?目前我正在订阅这样的频道:
cometdClient.getChannel("/chat/" + clientID).subscribe(new ChannelListener("/chat/ messages"), new ChannelListener("/chat/ progress"));
但它如预期的那样失败了。
顺便说一句,我使用 org.eclipse.jetty.client.HttpClient
作为 HttpClient。
首先,你真的应该升级,因为 CometD 2.9.1 现在真的很旧,JDK 7 在 Android 上受支持。
要求 /meta/subscribe
消息中包含所有这些字段的服务器设计确实是错误的。
大多数信息是静态的(例如 user
和各种 "cookies" 例如 pid
等)并且可以在 CometD 握手时确定,因此不需要发送它在订阅期间结束。
此外,在 /meta/subscribe
消息中发送它会使其受到攻击(例如,攻击者可以伪造具有不同 user
字段的消息)。你想阅读 security section of the CometD documentation.
此外,不推荐为每个用户使用一个频道(因为频道名称似乎是 /chat/
和 user
字段的串联),因为它可能会创建一个很多频道,而使用单个服务频道(并且 user
作为正在发送的消息的字段)可以更有效地实现相同的功能。
如果您真的必须将这些字段添加到 /meta/subscribe
消息中,方法是使用 custom extension,按照这些行:
class SubscribeExtension extends ClientSession.Extension.Adapter {
@Override
public boolean sendMeta(ClientSession session, Message.Mutable message) {
if (Channel.META_SUBSCRIBE.equals(message.getChannel())) {
String subscription = (String)message.get(Message.SUBSCRIPTION_FIELD);
if (subscription.startsWith("/chat/") {
// Add fields.
}
}
return true;
}
}
最后,如果您确实需要向 /meta/subscribe
消息添加额外的字段,您希望在 ext
字段中使用适当的命名空间进行操作:
{
"id": "3",
"channel": "/meta/subscribe",
"subscription": "/chat/xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
"clientId": "26l1v2ngpdcwdtno1wu30rk92dur4",
"ext": {
"com.acme.myapp": {
"time": 1234567890,
"pageId": "6ea23e",
...
}
}
}
请注意额外的字段如何不会污染消息本身,而是分组在命名空间 com.acme.app
下的 ext
字段中,这将代表您的公司和应用程序。