123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="channel-security"
- xmlns:xlink="http://www.w3.org/1999/xlink">
- <info>
- <title>Channel Security</title>
- </info>
- <section xml:id="channel-security-overview">
- <info>
- <title>Overview</title>
- </info>
- <para>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 <literal>HttpSession</literal> 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.</para>
- <para>An important issue in considering transport security is that of session hijacking.
- Your web container manages a <literal>HttpSession</literal> by reference to a
- <literal>jsessionid</literal> that is sent to user agents either via a cookie or URL
- rewriting. If the <literal>jsessionid</literal> 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.</para>
- <para>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
- <literal>jsessionid</literal> is never sent across an insecure channel. You will
- need to ensure your <literal>web.xml</literal>-defined
- <literal><welcome-file></literal> 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.</para>
- </section>
- <section xml:id="channel-security-config">
- <info>
- <title>Configuration</title>
- </info>
- <para>Channel security is supported by the <link xlink:href="#ns-requires-channel">security
- namespace</link> by means of the <literal>requires-channel</literal> attribute on
- the <literal><intercept-url></literal> element and this is the simplest (and
- recommended approach).</para>
- <para>To configure channel security explicitly, you would define the following the filter in
- your application context: <programlisting><![CDATA[
- <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.access.channel.ChannelDecisionManagerImpl">
- <property name="channelProcessors">
- <list>
- <ref bean="secureChannelProcessor"/>
- <ref bean="insecureChannelProcessor"/>
- </list>
- </property>
- </bean>
- <bean id="secureChannelProcessor"
- class="org.springframework.security.access.channel.SecureChannelProcessor"/>
- <bean id="insecureChannelProcessor"
- class="org.springframework.security.access.channel.InsecureChannelProcessor"/>]]>
- </programlisting>
- Like <classname>FilterSecurityInterceptor</classname>, Apache Ant style paths are also
- supported by the <literal>ChannelProcessingFilter</literal>.</para>
- <para>The <literal>ChannelProcessingFilter</literal> operates by filtering all web requests
- and determining the configuration attributes that apply. It then delegates to the
- <literal>ChannelDecisionManager</literal>. The default implementation,
- <literal>ChannelDecisionManagerImpl</literal>, should suffice in most cases. It
- simply delegates to the list of configured <literal>ChannelProcessor</literal>
- instances. The attribute <literal>ANY_CHANNEL</literal> can be used to override this
- behaviour and skip a particular URL. Otherwise, a <literal>ChannelProcessor</literal>
- 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.</para>
- <para>Included with Spring Security are two concrete <literal>ChannelProcessor</literal>
- implementations: <literal>SecureChannelProcessor</literal> ensures requests with a
- configuration attribute of <literal>REQUIRES_SECURE_CHANNEL</literal> are received over
- HTTPS, whilst <literal>InsecureChannelProcessor</literal> ensures requests with a
- configuration attribute of <literal>REQUIRES_INSECURE_CHANNEL</literal> are received
- over HTTP. Both implementations delegate to a <literal>ChannelEntryPoint</literal> if
- the required transport protocol is not used. The two
- <literal>ChannelEntryPoint</literal> implementations included with Spring Security
- simply redirect the request to HTTP and HTTPS as appropriate. Appropriate defaults are
- assigned to the <literal>ChannelProcessor</literal> implementations for the
- configuration attribute keywords they respond to and the
- <interfacename>ChannelEntryPoint</interfacename> they delegate to, although you have
- the ability to override these using the application context.</para>
- <para>Note that the redirections are absolute (eg
- <literal>http://www.company.com:8080/app/page</literal>), not relative (eg
- <literal>/app/page</literal>). 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
- <classname>PortResolverImpl</classname> that is wired up by default to many Spring
- Security beans. Please refer to the JavaDocs for <classname>PortResolverImpl</classname>
- for further details.</para>
- <para>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
- <classname>ChannelProcessingFilter</classname> with form-based login, please ensure
- that your login page is set to <literal>REQUIRES_SECURE_CHANNEL</literal>, and that the
- <literal>LoginUrlAuthenticationEntryPoint.forceHttps</literal> property is
- <literal>true</literal>.</para>
- </section>
- <section xml:id="channel-security-conclusion">
- <info>
- <title>Conclusion</title>
- </info>
- <para>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
- <literal>web.xml</literal>
- <literal><welcome-file></literal> or a well-known home page URL), but once this is
- done the filter will perform redirects as defined by your application context.</para>
- <para>You can also add your own <literal>ChannelProcessor</literal> implementations to the
- <literal>ChannelDecisionManagerImpl</literal>. For example, you might set a
- <literal>HttpSession</literal> attribute when a human user is detected via a "enter
- the contents of this graphic" procedure. Your <literal>ChannelProcessor</literal> would
- respond to say <literal>REQUIRES_HUMAN_USER</literal> configuration attributes and
- redirect to an appropriate entry point to start the human user validation process if the
- <literal>HttpSession</literal> attribute is not currently set.</para>
- <para>To decide whether a security check belongs in a <literal>ChannelProcessor</literal> or
- an <interfacename>AccessDecisionVoter</interfacename>, 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
- <literal>ChannelProcessor</literal> will generally cause an HTTP/HTTPS redirection
- so its requirements can be met, whilst problems detected by an
- <interfacename>AccessDecisionVoter</interfacename> will ultimately result in an
- <literal>AccessDeniedException</literal> (depending on the governing
- <interfacename>AccessDecisionManager</interfacename>).</para>
- </section>
- </chapter>
|