I have an existing Spring MVC application which has @PreAuthorize annotations
on the business services. I would like to add the ability for a
client/system to send JMS Messages which, in-turn, calls methods on those
secured spring beans. /FYI, without the @PreAuthorize annotation the
call's work seamlessly./
Reading the Camel Wiki on Spring-Security
(http://camel.apache.org/spring-security.html), it looks like I should be
able to put a spring authentication token wrapped as a Subject principal
into the Exchange.AUTHENTICATION Header and send it over the wire.
However, I get the error
"org.springframework.security.authentication.AuthenticationCredentialsNotFoundException:
An Authentication object was not found in the SecurityContext".
I had implemented an AuthenticationAdapter expecting to see calls to convert
from Subject back to Authentication objects. Obviously, the Authentication
object is not put back into a security context, nor was any additional
authentication logic called off to.
Since that didn't prove useful, I decided to wrap the "camel:to" with a
"camel:policy" as described in the spring-security section in hopes it would
yield some better results (even though I don't want to apply policies to
routes). I then received an error from the
SpringSecurityAuthorizationPolicy. Digging into it, it shows that there is
not an instance of the Subject class in the headers.
Given that information, I tried adding custom filter header strategies after
observing that the JMSHeaderFilterStrategy was being used, which doesn't
look like it will include the needed Subject header; still with no luck.
After a lot of time putting the strategies on combinations of sending and
receiving ends of the queue with no success, I decided I had to look for
help and determine if maybe the concept was flawed or there was even a path
to my solution.
So, I ask, should this concept work? If so, what's the missing-link that's
needed to make this work?
Here are the versions from my POM.
<spring.version>3.1.2.RELEASE</spring.version>
<spring-security.version>3.1.2.RELEASE</spring-security.version>
<spring-integration.version>2.1.3.RELEASE</spring-integration.version>
<spring-ws.version>2.1.1.RELEASE-SNAPSHOT</spring-ws.version>
<hibernate.version>4.1.4.Final</hibernate.version>
<aspectj.version>1.7.0</aspectj.version>
<activemq.version>5.6.0</activemq.version>
<camel.version>2.10.2</camel.version>
<xbean-spring.version>3.11.1</xbean-spring.version>
<slf4j.version>1.6.6</slf4j.version>
And since everyone likes code and configuration...
*INTERFACE*
import org.springframework.security.access.prepost.PreAuthorize;
public interface AMathService {
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
String sayHello(String name);
}
*IMPLEMENTATION*
import org.springframework.stereotype.Service;
@Service("aMathService")
public class AMathServiceImpl implements AMathService {
@Override
public String sayHello(String name) {
return new String("hello " + name);
}
}
*ROUTE(no strategy)*
<camel:route id="sayHello">
<camel:from uri="jms:queue:hello"/>
<camel:policy ref="admin">
<camel:to uri="bean:aMathService?method=sayHello(String)" />
</camel:policy>
</camel:route>
*ROUTE(with strategy)*
<camel:route id="sayHello">
<camel:from
uri="jms:queue:hello?headerFilterStrategy=#camelToSpringHeaderFilterStrategy"/>
<camel:policy ref="admin">
<camel:to uri="bean:aMathService?method=sayHello(String)" />
</camel:policy>
</camel:route>
*CLIENT (option a)*
GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
GrantedAuthority a = new SimpleGrantedAuthority("ROLE_ADMIN");
authorities.add(a);
Authentication auth = new
org.springframework.security.authentication.UsernamePasswordAuthenticationToken("abcdefg",
"1234", authorities);
Subject subject = new javax.security.auth.Subject();
subject.getPrincipals().add(auth);
Endpoint endpoint = camel.getEndpoint("jms:queue:hello");
System.out.println(camelTemplate.requestBodyAndHeader(endpoint, "john" ,
Exchange.AUTHENTICATION, subject));
*CLIENT (option b)*
Producer producer = endpoint.createProducer();
producer.start();
Exchange exchange = endpoint.createExchange(ExchangePattern.InOut);
exchange.getIn().setBody("john");
exchange.getIn().getHeaders().put(Exchange.AUTHENTICATION, subject);
producer.process(exchange);
System.out.println(".. the result is " + exchange.getOut().getBody());
producer.stop();
--
View this message in context:
http://camel.465427.n5.nabble.com/JMS-to-Secured-Spring-Method-with-PreAuthorize-annotation-tp5722696.html
Sent from the Camel - Users mailing list archive at Nabble.com.