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.

Reply via email to