You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2026/05/28 14:42:52 UTC
(camel) branch camel-4.14.x updated: [backport camel-4.14.x] CAMEL-23592: camel-shiro - align Exchange header constant names with Camel naming convention (#23559)
This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch camel-4.14.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.14.x by this push:
new a3d35e923122 [backport camel-4.14.x] CAMEL-23592: camel-shiro - align Exchange header constant names with Camel naming convention (#23559)
a3d35e923122 is described below
commit a3d35e9231225149f3dd45fb6c10313d85bdf518
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Thu May 28 16:42:42 2026 +0200
[backport camel-4.14.x] CAMEL-23592: camel-shiro - align Exchange header constant names with Camel naming convention (#23559)
* CAMEL-23592: camel-shiro - align Exchange header constant names with Camel naming convention (#23506)
Renames the three Exchange header string values in ShiroSecurityConstants
that drive Shiro authentication (SHIRO_SECURITY_TOKEN,
SHIRO_SECURITY_USERNAME, SHIRO_SECURITY_PASSWORD) to CamelShiroSecurity<Name>,
following the convention used across the rest of the Camel component catalog
and matching the pattern established in CAMEL-23526 (camel-cxf), CAMEL-23522
(camel-mail), CAMEL-23461 (camel-aws-bedrock), CAMEL-23532
(camel-vertx-websocket / camel-atmosphere-websocket / camel-iggy), and
CAMEL-23576 (camel-jira).
- SHIRO_SECURITY_TOKEN: "SHIRO_SECURITY_TOKEN" -> "CamelShiroSecurityToken"
- SHIRO_SECURITY_USERNAME: "SHIRO_SECURITY_USERNAME" -> "CamelShiroSecurityUsername"
- SHIRO_SECURITY_PASSWORD: "SHIRO_SECURITY_PASSWORD" -> "CamelShiroSecurityPassword"
These headers carry credentials and a serialized authentication token, so
filtering them at transport boundaries by default is particularly important.
The Java field names are unchanged so routes referencing the constants
symbolically continue to work; routes using the literal string values must be
updated (documented in the 4.21 upgrade guide). No tests reference the
literal values, and the shiro adoc documentation references the constants
symbolically.
Tracker: CAMEL-23577
Reported by Claude Code on behalf of Andrea Cosentino
Signed-off-by: Andrea Cosentino <an...@gmail.com>
* CAMEL-23592: camel-itest - update ShiroOverJmsTest for renamed Shiro security headers
After CAMEL-23592 the three Shiro security header values move into the
Camel* namespace (CamelShiroSecurityToken etc.). The default
JmsHeaderFilterStrategy filters every Camel* header at the transport
boundary, which is the intended behavior for untrusted producers but
strips the serialized authentication token from trusted Shiro-over-JMS
routes that previously relied on the old non-Camel-prefixed value
surviving the JMS round-trip.
ShiroOverJmsTest is exactly such a trusted Shiro-over-JMS route and
was failing on this backport branch's CI:
mock://ShiroOverJmsTestError Received message count.
Expected: <0> but was: <1>
(the consumer-side ShiroSecurityPolicy could no longer read the token
and the message ended up at the dead-letter mock). The same regression
exists latently on main; the matching fix is in PR #23592, and PR #23552
applies it to the 4.18.x backport.
- ShiroOverJmsTest: configure a small subclass of JmsHeaderFilterStrategy
on the JMS component that opts the three Shiro security headers back in
(returns false from applyFilterToCamelHeaders /
applyFilterToExternalHeaders for those headers, delegates to super for
everything else). This is the pattern end-users will need.
- 4.14 upgrade guide: extend the camel-shiro entry to document the new
required HeaderFilterStrategy opt-in for trusted Shiro-over-transport
routes, with a worked code example mirroring the one used in the test.
Co-Authored-By: Claude Opus 4.7 (1M context) <no...@anthropic.com>
Signed-off-by: Andrea Cosentino <an...@gmail.com>
---------
Signed-off-by: Andrea Cosentino <an...@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <no...@anthropic.com>
---
.../shiro/security/ShiroSecurityConstants.java | 6 +-
.../ROOT/pages/camel-4x-upgrade-guide-4_14.adoc | 64 ++++++++++++++++++++++
.../apache/camel/itest/shiro/ShiroOverJmsTest.java | 35 ++++++++++++
3 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/components/camel-shiro/src/main/java/org/apache/camel/component/shiro/security/ShiroSecurityConstants.java b/components/camel-shiro/src/main/java/org/apache/camel/component/shiro/security/ShiroSecurityConstants.java
index b3b30e800efa..4f8e7d21e5ad 100644
--- a/components/camel-shiro/src/main/java/org/apache/camel/component/shiro/security/ShiroSecurityConstants.java
+++ b/components/camel-shiro/src/main/java/org/apache/camel/component/shiro/security/ShiroSecurityConstants.java
@@ -21,9 +21,9 @@ package org.apache.camel.component.shiro.security;
*/
public final class ShiroSecurityConstants {
- public static final String SHIRO_SECURITY_TOKEN = "SHIRO_SECURITY_TOKEN";
- public static final String SHIRO_SECURITY_USERNAME = "SHIRO_SECURITY_USERNAME";
- public static final String SHIRO_SECURITY_PASSWORD = "SHIRO_SECURITY_PASSWORD";
+ public static final String SHIRO_SECURITY_TOKEN = "CamelShiroSecurityToken";
+ public static final String SHIRO_SECURITY_USERNAME = "CamelShiroSecurityUsername";
+ public static final String SHIRO_SECURITY_PASSWORD = "CamelShiroSecurityPassword";
private ShiroSecurityConstants() {
}
diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
index 7e2113be5a7a..b3e3c195b2b3 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
@@ -242,6 +242,70 @@ As a consequence, the generated Endpoint DSL header accessors on
`resultClassType()` -> `arangoDbResultClassType()`.
+=== camel-shiro - potential breaking change
+
+The three Exchange header constants in `ShiroSecurityConstants` that drive
+Shiro authentication used header values outside the `Camel` namespace
+(`SHIRO_SECURITY_TOKEN`, `SHIRO_SECURITY_USERNAME`, `SHIRO_SECURITY_PASSWORD`)
+and were therefore not filtered by the default `HeaderFilterStrategy`. They
+have been renamed to follow the Camel naming convention. The Java field names
+are unchanged; only the header string values have changed:
+
+[options="header"]
+|===
+| Constant | Previous value | New value
+| `ShiroSecurityConstants.SHIRO_SECURITY_TOKEN` | `SHIRO_SECURITY_TOKEN` | `CamelShiroSecurityToken`
+| `ShiroSecurityConstants.SHIRO_SECURITY_USERNAME` | `SHIRO_SECURITY_USERNAME` | `CamelShiroSecurityUsername`
+| `ShiroSecurityConstants.SHIRO_SECURITY_PASSWORD` | `SHIRO_SECURITY_PASSWORD` | `CamelShiroSecurityPassword`
+|===
+
+These headers carry credentials and a serialized authentication token, so
+filtering them at transport boundaries by default is particularly important.
+
+Routes that reference the constants symbolically (for example
+`setHeader(ShiroSecurityConstants.SHIRO_SECURITY_USERNAME, ...)`) continue to
+work without changes. Routes that set the header by its literal string value
+(for example `setHeader("SHIRO_SECURITY_USERNAME", ...)`) must be updated to
+use the new value (`setHeader("CamelShiroSecurityUsername", ...)`).
+
+Because the three header values are now in the `Camel*` namespace, transports
+that filter Camel-internal headers by default (JMS, CXF, HTTP, etc.) will
+strip the serialized Shiro authentication token before publishing. This is
+the intended behavior for untrusted producers. Trusted Shiro-over-transport
+routes that previously relied on the token surviving the boundary must opt
+those three headers back in via a custom `HeaderFilterStrategy`, for example:
+
+[source,java]
+----
+public class ShiroFriendlyJmsHeaderFilterStrategy extends JmsHeaderFilterStrategy {
+ @Override
+ public boolean applyFilterToCamelHeaders(String name, Object value, Exchange ex) {
+ if (isShiroSecurityHeader(name)) {
+ return false;
+ }
+ return super.applyFilterToCamelHeaders(name, value, ex);
+ }
+
+ @Override
+ public boolean applyFilterToExternalHeaders(String name, Object value, Exchange ex) {
+ if (isShiroSecurityHeader(name)) {
+ return false;
+ }
+ return super.applyFilterToExternalHeaders(name, value, ex);
+ }
+
+ private static boolean isShiroSecurityHeader(String name) {
+ return ShiroSecurityConstants.SHIRO_SECURITY_TOKEN.equalsIgnoreCase(name)
+ || ShiroSecurityConstants.SHIRO_SECURITY_USERNAME.equalsIgnoreCase(name)
+ || ShiroSecurityConstants.SHIRO_SECURITY_PASSWORD.equalsIgnoreCase(name);
+ }
+}
+
+jmsComponent.setHeaderFilterStrategy(new ShiroFriendlyJmsHeaderFilterStrategy());
+----
+
+A worked example is in `ShiroOverJmsTest` in the `camel-itest` module.
+
== Upgrading from 4.14.5 to 4.14.6
=== camel-platform-http-main
diff --git a/tests/camel-itest/src/test/java/org/apache/camel/itest/shiro/ShiroOverJmsTest.java b/tests/camel-itest/src/test/java/org/apache/camel/itest/shiro/ShiroOverJmsTest.java
index ccd5e8b2661f..5a702f8e9da8 100644
--- a/tests/camel-itest/src/test/java/org/apache/camel/itest/shiro/ShiroOverJmsTest.java
+++ b/tests/camel-itest/src/test/java/org/apache/camel/itest/shiro/ShiroOverJmsTest.java
@@ -19,8 +19,10 @@ package org.apache.camel.itest.shiro;
import java.util.HashMap;
import java.util.Map;
+import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
+import org.apache.camel.component.jms.JmsHeaderFilterStrategy;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.component.shiro.security.ShiroSecurityConstants;
import org.apache.camel.component.shiro.security.ShiroSecurityPolicy;
@@ -61,9 +63,42 @@ public class ShiroOverJmsTest extends CamelTestSupport {
amq.setCamelContext(context);
+ // After CAMEL-23592 the Shiro security headers live in the CamelShiroSecurity* namespace,
+ // which the default JmsHeaderFilterStrategy filters at the transport boundary. For a
+ // trusted Shiro-over-JMS route, the operator must opt those three headers back in.
+ amq.setHeaderFilterStrategy(new ShiroFriendlyJmsHeaderFilterStrategy());
+
registry.bind("jms", amq);
}
+ /**
+ * Allows the three Shiro security headers (token, username, password) to cross the JMS transport boundary while
+ * still filtering every other Camel-internal header.
+ */
+ private static final class ShiroFriendlyJmsHeaderFilterStrategy extends JmsHeaderFilterStrategy {
+ @Override
+ public boolean applyFilterToCamelHeaders(String headerName, Object headerValue, Exchange exchange) {
+ if (isShiroSecurityHeader(headerName)) {
+ return false;
+ }
+ return super.applyFilterToCamelHeaders(headerName, headerValue, exchange);
+ }
+
+ @Override
+ public boolean applyFilterToExternalHeaders(String headerName, Object headerValue, Exchange exchange) {
+ if (isShiroSecurityHeader(headerName)) {
+ return false;
+ }
+ return super.applyFilterToExternalHeaders(headerName, headerValue, exchange);
+ }
+
+ private static boolean isShiroSecurityHeader(String headerName) {
+ return ShiroSecurityConstants.SHIRO_SECURITY_TOKEN.equalsIgnoreCase(headerName)
+ || ShiroSecurityConstants.SHIRO_SECURITY_USERNAME.equalsIgnoreCase(headerName)
+ || ShiroSecurityConstants.SHIRO_SECURITY_PASSWORD.equalsIgnoreCase(headerName);
+ }
+ }
+
@Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {