The process of obtaining security credentials that are used for authorization is not
specified by this component. You can write your own processors or components which get
authentication information from the exchange depending on your needs. For example, you might
create a processor that gets credentials from an HTTP request header originating in the
camel-jetty component. No matter how the credentials are collected, they need to be placed
in the In message or the SecurityContextHolder
so the camel-spring-security component can access them:
import javax.security.auth.Subject; import org.apache.camel.*; import org.apache.commons.codec.binary.Base64; import org.springframework.security.authentication.*; public class MyAuthService implements Processor { public void process(Exchange exchange) throws Exception { // get the username and password from the HTTP header // http://en.wikipedia.org/wiki/Basic_access_authentication String userpass = new String(Base64.decodeBase64( exchange.getIn().getHeader("Authorization", String.class))); String[] tokens = userpass.split(":"); // create an Authentication object UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(tokens[0], tokens[1]); // wrap it in a Subject Subject subject = new Subject(); subject.getPrincipals().add(authToken); // place the Subject in the In message exchange.getIn().setHeader(Exchange.AUTHENTICATION, subject); // You could also do this if useThreadSecurityContext is set to true: // SecurityContextHolder.getContext().setAuthentication(authToken); } }
The SpringSecurityAuthorizationPolicy
will automatically authenticate the
Authentication
object if necessary.
There are two issues to be aware of when using the SecurityContextHolder
instead of or in addition to the Exchange.AUTHENTICATION
header. First, the
context holder uses a thread-local variable to hold the Authentication
object.
Any routes that cross thread boundaries, like seda or
jms, will lose the Authentication
object.
Second, the Spring Security system appears to expect that an Authentication
object in the context is already authenticated and has roles (see the Technical Overview
section 5.3.1 for more details).
The default behavior of camel-spring-security is to
look for a Subject
in the Exchange.AUTHENTICATION
header. This
Subject
must contain at least one principal, which must be a subclass of
org.springframework.security.core.Authentication
. You can customize the
mapping of Subject
to Authentication
object by providing an
implementation of the
org.apache.camel.component.spring.security.AuthenticationAdapter
to your
<authorizationPolicy>
bean. This can be useful if you are working with
components that do not use Spring Security but do provide a Subject
. At this
time, only the camel-cxf component populates the Exchange.AUTHENTICATION
header.