You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by "john.moore@kronos.com" <jo...@kronos.com> on 2012/11/13 23:55:56 UTC

JMS to Secured Spring Method with PreAuthorize annotation

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.

Re: JMS to Secured Spring Method with PreAuthorize annotation

Posted by "John.R.Moore" <jo...@kronos.com>.
Thanks to you both for pointing me in the right direction.  Tried both the
transfer and adding base64 encoded header and was able to move past the
method authentication hurdle.    I had quick successes with the base 64
option using processors to get the authentication information
encoded/decoded.

John



--
View this message in context: http://camel.465427.n5.nabble.com/JMS-to-Secured-Spring-Method-with-PreAuthorize-annotation-tp5722696p5722754.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: JMS to Secured Spring Method with PreAuthorize annotation

Posted by Claus Ibsen <cl...@gmail.com>.
On Wed, Nov 14, 2012 at 2:19 AM, Willem jiang <wi...@gmail.com> wrote:
> It looks like you need to pass the SecurityContext across the JMS endpoint.
> when you using the camel-jms component, it will transfer the exchange which hold the SecurityContext for you if you set the "transferExchange" option to be true.
>
>

Ah yeah this has also been talked about before on this @user list.

That other person would base64 encode the auth token so it could be
transferred over JMS, and then assemble it again when receiving the
JMS message.

We could consider having some sort of functionality for that in
camel-spring-security, so people can turn this on, and transfer over
networks.

> --
> Willem Jiang
>
> Red Hat, Inc.
> FuseSource is now part of Red Hat
> Web: http://www.fusesource.com | http://www.redhat.com
> Blog: http://willemjiang.blogspot.com (http://willemjiang.blogspot.com/) (English)
>           http://jnn.javaeye.com (http://jnn.javaeye.com/) (Chinese)
> Twitter: willemjiang
> Weibo: willemjiang
>
>
>
>
>
> On Wednesday, November 14, 2012 at 6:55 AM, john.moore@kronos.com wrote:
>
>> 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 (http://Nabble.com).
>
>
>



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
FuseSource is now part of Red Hat
Email: cibsen@redhat.com
Web: http://fusesource.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen

Re: JMS to Secured Spring Method with PreAuthorize annotation

Posted by Willem jiang <wi...@gmail.com>.
It looks like you need to pass the SecurityContext across the JMS endpoint.
when you using the camel-jms component, it will transfer the exchange which hold the SecurityContext for you if you set the "transferExchange" option to be true.


-- 
Willem Jiang

Red Hat, Inc.
FuseSource is now part of Red Hat
Web: http://www.fusesource.com | http://www.redhat.com
Blog: http://willemjiang.blogspot.com (http://willemjiang.blogspot.com/) (English)
          http://jnn.javaeye.com (http://jnn.javaeye.com/) (Chinese)
Twitter: willemjiang 
Weibo: willemjiang





On Wednesday, November 14, 2012 at 6:55 AM, john.moore@kronos.com wrote:

> 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 (http://Nabble.com).