| [[spring-security-component]] |
| = Spring Security Component |
| //THIS FILE IS COPIED: EDIT THE SOURCE FILE: |
| :page-source: components/camel-spring-security/src/main/docs/spring-security.adoc |
| :docTitle: Spring Security |
| :artifactId: camel-spring-security |
| :description: Security using Spring Security |
| :since: 2.3 |
| :supportLevel: Stable |
| //Manually maintained attributes |
| :group: Spring |
| |
| *Since Camel {since}* |
| |
| The Camel Spring Security component provides role-based authorization |
| for Camel routes. It leverages the authentication and user services |
| provided by |
| https://spring.io/projects/spring-security[Spring |
| Security] (formerly Acegi Security) and adds a declarative, role-based |
| policy system to control whether a route can be executed by a given |
| principal. |
| |
| If you are not familiar with the Spring Security authentication and |
| authorization system, please review the current reference documentation |
| on the SpringSource web site linked above. |
| |
| [[SpringSecurity-Creatingauthorizationpolicies]] |
| == Creating authorization policies |
| |
| Access to a route is controlled by an instance of a |
| `SpringSecurityAuthorizationPolicy` object. A policy object contains the |
| name of the Spring Security authority (role) required to run a set of |
| endpoints and references to Spring Security `AuthenticationManager` and |
| `AccessDecisionManager` objects used to determine whether the current |
| principal has been assigned that role. Policy objects may be configured |
| as Spring beans or by using an `<authorizationPolicy>` element in Spring |
| XML. |
| |
| The `<authorizationPolicy>` element may contain the following |
| attributes: |
| |
| [width="100%",cols="10%,10%,80%",options="header",] |
| |======================================================================= |
| |Name |Default Value |Description |
| |
| |`id` |`null` |The unique Spring bean identifier which is used to reference the policy |
| in routes (required) |
| |
| |`access` |`null` |The Spring Security authority name that is passed to the access decision |
| manager (required) |
| |
| |`authenticationManager` |`authenticationManager` |The name of the Spring Security `AuthenticationManager` object in the |
| context |
| |
| |`accessDecisionManager` |`accessDecisionManager` |The name of the Spring Security `AccessDecisionManager` object in the |
| context |
| |
| |`authenticationAdapter` |DefaultAuthenticationAdapter |The name of a *camel-spring-security* |
| `AuthenticationAdapter` object in the context that is used to convert a |
| `javax.security.auth.Subject` into a Spring Security `Authentication` |
| instance. |
| |
| |`useThreadSecurityContext` |`true` |If a `javax.security.auth.Subject` cannot be found in the In message |
| header under Exchange.AUTHENTICATION, check the Spring Security |
| `SecurityContextHolder` for an `Authentication` object. |
| |
| |`alwaysReauthenticate` |`false` |If set to true, the `SpringSecurityAuthorizationPolicy` will always call |
| `AuthenticationManager.authenticate()` each time the policy is accessed. |
| |======================================================================= |
| |
| [[SpringSecurity-ControllingaccesstoCamelroutes]] |
| == Controlling access to Camel routes |
| |
| A Spring Security `AuthenticationManager` and `AccessDecisionManager` |
| are required to use this component. Here is an example of how to |
| configure these objects in Spring XML using the Spring Security |
| namespace: |
| |
| [source,xml] |
| ---- |
| <beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xmlns:spring-security="http://www.springframework.org/schema/security" |
| xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd |
| http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> |
| |
| <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> |
| <property name="allowIfAllAbstainDecisions" value="true"/> |
| <property name="decisionVoters"> |
| <list> |
| <bean class="org.springframework.security.access.vote.RoleVoter"/> |
| </list> |
| </property> |
| </bean> |
| |
| <spring-security:authentication-manager alias="authenticationManager"> |
| <spring-security:authentication-provider user-service-ref="userDetailsService"/> |
| </spring-security:authentication-manager> |
| |
| <spring-security:user-service id="userDetailsService"> |
| <spring-security:user name="jim" password="jimspassword" authorities="ROLE_USER, ROLE_ADMIN"/> |
| <spring-security:user name="bob" password="bobspassword" authorities="ROLE_USER"/> |
| </spring-security:user-service> |
| |
| </beans> |
| ---- |
| |
| Now that the underlying security objects are set up, we can use them to |
| configure an authorization policy and use that policy to control access |
| to a route: |
| |
| [source,xml] |
| ---- |
| <beans xmlns="http://www.springframework.org/schema/beans" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xmlns:spring-security="http://www.springframework.org/schema/security" |
| xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd |
| http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd |
| http://camel.apache.org/schema/spring-security http://camel.apache.org/schema/spring-security/camel-spring-security.xsd |
| http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> |
| |
| <!-- import the Spring security configuration --> |
| <import resource= "classpath:org/apache/camel/component/spring/security/commonSecurity.xml"/> |
| |
| <authorizationPolicy id="admin" access="ROLE_ADMIN" |
| authenticationManager="authenticationManager" |
| accessDecisionManager="accessDecisionManager" |
| xmlns="http://camel.apache.org/schema/spring-security"/> |
| |
| <camelContext id="myCamelContext" xmlns="http://camel.apache.org/schema/spring"> |
| <route> |
| <from uri="direct:start"/> |
| <!-- The exchange should be authenticated with the role --> |
| <!-- of ADMIN before it is send to mock:endpoint --> |
| <policy ref="admin"> |
| <to uri="mock:end"/> |
| </policy> |
| </route> |
| </camelContext> |
| </beans> |
| ---- |
| |
| In this example, the endpoint `mock:end` will not be executed unless a |
| Spring Security `Authentication` object that has been or can be |
| authenticated and contains the `ROLE_ADMIN` authority can be located by |
| the _admin_ `SpringSecurityAuthorizationPolicy`. |
| |
| [[SpringSecurity-Authentication]] |
| == Authentication |
| |
| 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 xref:ROOT:jetty-component.adoc[Jetty] component. No matter how the credentials |
| are collected, they need to be placed in the In message or the |
| `SecurityContextHolder` so the Camel xref:spring-security.adoc[Spring |
| Security] component can access them: |
| |
| [source,java] |
| ---- |
| 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 |
| http://static.springsource.org/spring-security/site/docs/3.0.x/reference/technical-overview.html#tech-intro-authentication[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 xref:ROOT:cxf-component.adoc[CXF] component populates |
| the `Exchange.AUTHENTICATION` header. |
| |
| [[SpringSecurity-Handlingauthenticationandauthorizationerrors]] |
| == Handling authentication and authorization errors |
| |
| If authentication or authorization fails in the |
| `SpringSecurityAuthorizationPolicy`, a `CamelAuthorizationException` |
| will be thrown. This can be handled using Camel's standard exception |
| handling methods, like the Exception Clause. |
| The `CamelAuthorizationException` will have a reference to the ID of the |
| policy which threw the exception so you can handle errors based on the |
| policy as well as the type of exception: |
| |
| [source,xml] |
| ---- |
| <onException> |
| <exception>org.springframework.security.authentication.AccessDeniedException</exception> |
| <choice> |
| <when> |
| <simple>${exception.policyId} == 'user'</simple> |
| <transform> |
| <constant>You do not have ROLE_USER access!</constant> |
| </transform> |
| </when> |
| <when> |
| <simple>${exception.policyId} == 'admin'</simple> |
| <transform> |
| <constant>You do not have ROLE_ADMIN access!</constant> |
| </transform> |
| </when> |
| </choice> |
| </onException> |
| ---- |
| |