# Channel Security

## Overview

In addition to coordinating the authentication and authorization requirements of your application, Spring Security is also able to ensure unauthenticated web requests have certain properties. These properties may include being of a particular transport type, having a particular `HttpSession` attribute set and so on. The most common requirement is for your web requests to be received using a particular transport protocol, such as HTTPS.

An important issue in considering transport security is that of session hijacking. Your web container manages a `HttpSession` by reference to a `jsessionid` that is sent to user agents either via a cookie or URL rewriting. If the `jsessionid` is ever sent over HTTP, there is a possibility that session identifier can be intercepted and used to impersonate the user after they complete the authentication process. This is because most web containers maintain the same session identifier for a given user, even after they switch from HTTP to HTTPS pages.

If session hijacking is considered too significant a risk for your particular application, the only option is to use HTTPS for every request. This means the `jsessionid` is never sent across an insecure channel. You will need to ensure your `web.xml`-defined `<welcome-file>` points to an HTTPS location, and the application never directs the user to an HTTP location. Spring Security provides a solution to assist with the latter.

## Configuration

Channel security is supported by the security namespace by means of the `requires-channel` attribute on the `<intercept-url>` element and this is the simplest (and recommended approach).

To configure channel security explicitly, you would define the following the filter in your application context:

    <bean id="channelProcessingFilter"
        class="org.springframework.security.web.access.channel.ChannelProcessingFilter">
      <property name="channelDecisionManager" ref="channelDecisionManager"/>
      <property name="securityMetadataSource">
        <security:filter-security-metadata-source path-type="regex">
          <security:intercept-url pattern="\A/secure/.*\Z"
              access="REQUIRES_SECURE_CHANNEL"/>
          <security:intercept-url pattern="\A/acegilogin.jsp.*\Z"
              access="REQUIRES_SECURE_CHANNEL"/>
          <security:intercept-url pattern="\A/j_spring_security_check.*\Z"
              access="REQUIRES_SECURE_CHANNEL"/>
          <security:intercept-url pattern="\A/.*\Z" access="ANY_CHANNEL"/>
        </security:filter-security-metadata-source>
      </property>
    </bean>

    <bean id="channelDecisionManager"
        class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl">
      <property name="channelProcessors">
        <list>
        <ref bean="secureChannelProcessor"/>
        <ref bean="insecureChannelProcessor"/>
        </list>
      </property>
    </bean>

    <bean id="secureChannelProcessor"
      class="org.springframework.security.web.access.channel.SecureChannelProcessor"/>
    <bean id="insecureChannelProcessor"
      class="org.springframework.security.web.access.channel.InsecureChannelProcessor"/>

Like `FilterSecurityInterceptor`, Apache Ant style paths are also supported by the `ChannelProcessingFilter`.

The `ChannelProcessingFilter` operates by filtering all web requests and determining the configuration attributes that apply. It then delegates to the `ChannelDecisionManager`. The default implementation, `ChannelDecisionManagerImpl`, should suffice in most cases. It simply delegates to the list of configured `ChannelProcessor` instances. The attribute `ANY_CHANNEL` can be used to override this behaviour and skip a particular URL. Otherwise, a `ChannelProcessor` will review the request, and if it is unhappy with the request (e.g. if it was received across the incorrect transport protocol), it will perform a redirect, throw an exception or take whatever other action is appropriate.

Included with Spring Security are two concrete `ChannelProcessor` implementations: `SecureChannelProcessor` ensures requests with a configuration attribute of `REQUIRES_SECURE_CHANNEL` are received over HTTPS, whilst `InsecureChannelProcessor` ensures requests with a configuration attribute of `REQUIRES_INSECURE_CHANNEL` are received over HTTP. Both implementations delegate to a `ChannelEntryPoint` if the required transport protocol is not used. The two `ChannelEntryPoint` implementations included with Spring Security simply redirect the request to HTTP and HTTPS as appropriate. Appropriate defaults are assigned to the `ChannelProcessor` implementations for the configuration attribute keywords they respond to and the ChannelEntryPoint they delegate to, although you have the ability to override these using the application context.

Note that the redirections are absolute (eg `http://www.company.com:8080/app/page`), not relative (eg `/app/page`). During testing it was discovered that Internet Explorer 6 Service Pack 1 has a bug whereby it does not respond correctly to a redirection instruction which also changes the port to use. Accordingly, absolute URLs are used in conjunction with bug detection logic in the `PortResolverImpl` that is wired up by default to many Spring Security beans. Please refer to the JavaDocs for `PortResolverImpl` for further details.

You should note that using a secure channel is recommended if usernames and passwords are to be kept secure during the login process. If you do decide to use `ChannelProcessingFilter` with form-based login, please ensure that your login page is set to `REQUIRES_SECURE_CHANNEL`, and that the `LoginUrlAuthenticationEntryPoint.forceHttps` property is `true`.

## Conclusion

Once configured, using the channel security filter is very easy. Simply request pages without regard to the protocol (ie HTTP or HTTPS) or port (eg 80, 8080, 443, 8443 etc). Obviously you'll still need a way of making the initial request (probably via the `web.xml` `<welcome-file>` or a well-known home page URL), but once this is done the filter will perform redirects as defined by your application context.

You can also add your own `ChannelProcessor` implementations to the `ChannelDecisionManagerImpl`. For example, you might set a `HttpSession` attribute when a human user is detected via a "enter the contents of this graphic" procedure. Your `ChannelProcessor` would respond to say `REQUIRES_HUMAN_USER` configuration attributes and redirect to an appropriate entry point to start the human user validation process if the `HttpSession` attribute is not currently set.

To decide whether a security check belongs in a `ChannelProcessor` or an AccessDecisionVoter, remember that the former is designed to handle unauthenticated requests, whilst the latter is designed to handle authenticated requests. The latter therefore has access to the granted authorities of the authenticated principal. In addition, problems detected by a `ChannelProcessor` will generally cause an HTTP/HTTPS redirection so its requirements can be met, whilst problems detected by an AccessDecisionVoter will ultimately result in an `AccessDeniedException` (depending on the governing AccessDecisionManager).