浏览代码

manual updates

Luke Taylor 16 年之前
父节点
当前提交
d5aec71fac

+ 17 - 2
docs/manual/src/docbook/springsecurity.xml

@@ -97,8 +97,23 @@
         Security.</para>
     </partintro>
     <xi:include href="technical-overview.xml"/>
-    <xi:include href="supporting-infrastructure.xml"/>
-    <xi:include href="channel-security.xml"/>
+    <!--xi:include href="supporting-infrastructure.xml"/-->
+    <!-- xi:include href="channel-security.xml"/ -->
+  </part>
+
+  <part xml:id="webapp-security" >
+    <title>Web Application Security</title>
+    <partintro>
+      <para>
+        Most Spring Security users will be using the framework in enterprise applications which
+        make user of the HTTP and the Servlet API. In this part we'll take a look at how Spring Security provides
+        authentication and access-control features for the web layer of an application. We'll look
+        behind the facade of the namespace and see which classes and interfaces are actually assembled to provide web-layer
+        security. In some situations it is necessary to use traditional bean configuration to provide full control over 
+        the configuration, so we'll also see how to configure these classes directly without the namespace.
+      </para>
+    </partintro>
+    <xi:include href="supporting-infrastructure.xml"/>    
   </part>
   <part xml:id="authentication">
     <title>Authentication</title>

+ 126 - 214
docs/manual/src/docbook/supporting-infrastructure.xml

@@ -1,97 +1,32 @@
-<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="supporting-infrastructure" xmlns:xlink="http://www.w3.org/1999/xlink">
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="web-infrastructure" xmlns:xlink="http://www.w3.org/1999/xlink">
   
-  <info><title>Supporting Infrastructure</title></info>
-  
-
-  <para>This chapter introduces some of the supplementary and supporting
-  infrastructure used by Spring Security. If a capability is not directly
-  related to security, yet included in the Spring Security project, we
-  will discuss it in this chapter.</para>
-
-  <section xml:id="localization">
-    <title>Localization</title>
-    <para>Spring Security supports localization of exception messages that
-    end users are likely to see. If your application is designed for
-    English users, you don't need to do anything as by default all
-    Security Security messages are in English. If you need to support
-    other locales, everything you need to know is contained in this
-    section.</para>
-
-    <para>All exception messages can be localized, including messages
-    related to authentication failures and access being denied
-    (authorization failures). Exceptions and logging that is focused on
-    developers or system deployers (including incorrect attributes,
-    interface contract violations, using incorrect constructors, startup
-    time validation, debug-level logging) etc are not localized and
-    instead are hard-coded in English within Spring Security's
-    code.</para>
-
-    <para>Shipping in the <literal>spring-security-core-xx.jar</literal> you
-    will find an <literal>org.springframework.security</literal> package
-    that in turn contains a <literal>messages.properties</literal> file.
-    This should be referred to by your
-    <literal>ApplicationContext</literal>, as Spring Security classes
-    implement Spring's <literal>MessageSourceAware</literal> interface and
-    expect the message resolver to be dependency injected at application
-    context startup time. Usually all you need to do is register a bean
-    inside your application context to refer to the messages. An example
-    is shown below:</para>
-
-    <para><programlisting><![CDATA[
-<bean id="messageSource" 
-    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
-  <property name="basename" value="org/springframework/security/messages"/>
-</bean>
-]]></programlisting></para>
-
-    <para>The <literal>messages.properties</literal> is named in
-    accordance with standard resource bundles and represents the default
-    language supported by Spring Security messages. This default file is
-    in English. If you do not register a message source, Spring Security
-    will still work correctly and fallback to hard-coded English versions
-    of the messages.</para>
-
-    <para>If you wish to customize the
-    <literal>messages.properties</literal> file, or support other
-    languages, you should copy the file, rename it accordingly, and
-    register it inside the above bean definition. There are not a large
-    number of message keys inside this file, so localization should not be
-    considered a major initiative. If you do perform localization of this
-    file, please consider sharing your work with the community by logging
-    a JIRA task and attaching your appropriately-named localized version
-    of <literal>messages.properties</literal>.</para>
-
-    <para>Rounding out the discussion on localization is the Spring
-    <literal>ThreadLocal</literal> known as
-    <literal>org.springframework.context.i18n.LocaleContextHolder</literal>.
-    You should set the <literal>LocaleContextHolder</literal> to represent
-    the preferred <literal>Locale</literal> of each user. Spring Security
-    will attempt to locate a message from the message source using the
-    <literal>Locale</literal> obtained from this
-    <literal>ThreadLocal</literal>. Please refer to Spring documentation
-    for further details on using <literal>LocaleContextHolder</literal>
-    and the helper classes that can automatically set it for you (eg
-    <literal>AcceptHeaderLocaleResolver</literal>,
-    <literal>CookieLocaleResolver</literal>,
-    <literal>FixedLocaleResolver</literal>,
-    <literal>SessionLocaleResolver</literal> etc)</para>
-  </section>
+  <info><title>Web Security Infrastructure</title></info>
 
   <section xml:id="filters">
-    <info><title>Filters</title></info>
+    <title>Spring Security Filters</title>
 
-    <para>Spring Security uses many filters, as referred to throughout the
-      remainder of this reference guide. If you are using <link xlink:href="#ns-config">namespace configuration</link>,
-      then the you don't usually have to declare the filter beans explicitly. There may be times when you want full control
-      over the security filter chain, either because you are using features which aren't supported in the namespace, or you
-      are using your own customized versions of classes.</para>
-    <para>In this case, you have a choice in how these filters are added to your web application, in that you can use either
-        Spring's <literal>DelegatingFilterProxy</literal> or 
-    <classname>FilterChainProxy</classname>. We'll look at both below.</para>
-      
-    <para>When using <literal>DelegatingFilterProxy</literal>, you will see
-      something like this in the web.xml file:
-      
+    <para>Spring Security's web application features are implemented using standard servlet filters. It doesn't use
+      servlets or any other servlet-based frameworks (such as Spring MVC) internally. So it has no strong links to any 
+      particular web technology - it deals in <classname>HttpServletRequest</classname>s and <classname>HttpServletResponse</classname>s
+      and doesn't care whether the requests come from a browser, a web service client, an <classname>HttpInvoker</classname> or an AJAX application.
+    </para>
+    <para>
+      Spring Security maintains a filter chain internally where each of the filters has a particular responsibility and filters are added or removed
+      depending on which services are required. The ordering of the filters is important as there are dependencies between them.
+      If you have been using <link xlink:href="#ns-config">namespace configuration</link>, then the filters are automatically configured for you
+      and you don't have to define any Spring beans explicitly but here may be times when you want full control over the security filter chain, 
+      either because you are using features which aren't supported in the namespace, or you are using your own customized versions of classes.</para>
+    
+    <section xml:id="delegating-filter-proxy">
+      <title><classname>DelegatingFilterProxy</classname></title>
+      <para>
+        When using servlet filters, you obviously need to declare them in your <filename>web.xml</filename>, or they will be ignored 
+        by the servlet container. In Spring Security, the filter classes are also Spring beans defined in the application context and thus able 
+        to take advantage of Spring's rich dependency-injection facilities and lifecycle interfaces. Spring's <classname>DelegatingFilterProxy</classname>
+        provides the link between <filename>web.xml</filename> and the application context.
+      </para>
+      <para>When using <classname>DelegatingFilterProxy</classname>, you will see something like this in the <filename>web.xml</filename> file:
+        
         <programlisting><![CDATA[    
   <filter>
     <filter-name>myFilter</filter-name>
@@ -103,132 +38,111 @@
     <url-pattern>/*</url-pattern>
   </filter-mapping>]]>
         </programlisting>     
-       
-        Notice that the filter  is actually a <literal>DelegatingFilterProxy</literal>, 
-        and not the filter that will actually implement the logic of the filter. What
-        <literal>DelegatingFilterProxy</literal> does is delegate the
-    <literal>Filter</literal>'s methods through to a bean which is
-    obtained from the Spring application context. This enables the bean to
-    benefit from the Spring web application context lifecycle support and
-    configuration flexibility. The bean must implement
-    <literal>javax.servlet.Filter</literal> and it must have the same name as that in
-        the <literal>filter-name</literal> element.</para>
-
-    <para>There is a lifecycle issue to consider when hosting
-    <literal>Filter</literal>s in an IoC container instead of a servlet
-    container. Specifically, which container should be responsible for
-    calling the <literal>Filter</literal>'s "startup" and "shutdown"
-    methods? It is noted that the order of initialization and destruction
-    of a <literal>Filter</literal> can vary by servlet container, and this
-    can cause problems if one <literal>Filter</literal> depends on
-    configuration settings established by an earlier initialized
-    <literal>Filter</literal>. The Spring IoC container on the other hand
-    has more comprehensive lifecycle/IoC interfaces (such as
-    <literal>InitializingBean</literal>,
-    <literal>DisposableBean</literal>, <literal>BeanNameAware</literal>,
-    <literal>ApplicationContextAware</literal> and many others) as well as
-    a well-understood interface contract, predictable method invocation
-    ordering, autowiring support, and even options to avoid implementing
-    Spring interfaces (eg the <literal>destroy-method</literal> attribute
-    in Spring XML). For this reason we recommend the use of Spring
-    lifecycle services instead of servlet container lifecycle services
-    wherever possible. Read the Javadoc for <classname>DelegatingFilterProxy</classname>
-    for more information</para>
-
-      <para>Rather than using <literal>DelegatingFilterProxy</literal>, we
-    strongly recommend that you use <classname>FilterChainProxy</classname> instead.
-          Whilst <literal>DelegatingFilterProxy</literal> is a very useful class,
-    the problem is that the number of lines of code required for
-    <literal>&lt;filter&gt;</literal> and
-    <literal>&lt;filter-mapping&gt;</literal> entries in
-    <literal>web.xml</literal> explodes when using more than a few
-    filters. To overcome this issue, Spring Security provides a
-    <classname>FilterChainProxy</classname> class. It is wired using a
-          <literal>DelegatingFilterProxy</literal> (just like in the example above),
-    but the target class is
-    <literal>org.springframework.security.web.FilterChainProxy</literal>.
-    The filter chain is then declared in the application context, using
-    code such as this:</para>
-
-    <para><programlisting><![CDATA[
+        Notice that the filter is actually a <literal>DelegatingFilterProxy</literal>, 
+        and not the class that will actually implement the logic of the filter. What
+        <classname>DelegatingFilterProxy</classname> does is delegate the
+        <interfacename>Filter</interfacename>'s methods through to a bean which is
+        obtained from the Spring application context. This enables the bean to
+        benefit from the Spring web application context lifecycle support and
+        configuration flexibility. The bean must implement
+        <interfacename>javax.servlet.Filter</interfacename> and it must have the same name as that in
+        the <literal>filter-name</literal> element. Read the Javadoc for <classname>DelegatingFilterProxy</classname>
+        for more information</para>
+    </section>
+    <section xml:id="filter-chain-proxy">
+      <title><classname>FilterChainProxy</classname></title>
+      <para>
+        It should now be clear that you can declare each Spring Security filter bean that you require in your application context file and add a corresponding
+        <classname>DelegatingFilterProxy</classname> entry to <filename>web.xml</filename> for each filter, making sure that they are ordered correctly.
+        This is a cumbersome approach and clutters up the <filename>web.xml</filename> file quickly if we have a lot of filters. We would prefer to just add 
+        a single entry to <filename>web.xml</filename> and deal entirely with the application context file for managing our web security beans. 
+        This is where Spring Secuiryt's <classname>FilterChainProxy</classname> comes in. It is wired using a <literal>DelegatingFilterProxy</literal> 
+        (just like in the example above), but the target class is <classname>org.springframework.security.web.FilterChainProxy</classname>.
+        The filter chain is then declared in the application context. Here's an example:
+      <programlisting language="xml"><![CDATA[
 <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
   <sec:filter-chain-map path-type="ant">
      <sec:filter-chain pattern="/webServices/**" filters="
-           httpSessionContextIntegrationFilterWithASCFalse,
+           securityContextPersistenceFilterWithASCFalse,
            basicProcessingFilter,
            exceptionTranslationFilter,
            filterSecurityInterceptor" />
      <sec:filter-chain pattern="/**" filters="
-           httpSessionContextIntegrationFilterWithASCTrue,
+           securityContextPersistenceFilterWithASCTrue,
            authenticationProcessingFilter,
            exceptionTranslationFilter,
            filterSecurityInterceptor" />
   </sec:filter-chain-map>
 </bean>
 ]]>         
-    </programlisting></para>
-
-    <para>You may notice similarities with the way
-    <classname>FilterSecurityInterceptor</classname> is declared. Both regular
-    expressions and Ant Paths are supported, and the most specific URIs
-    appear first. At runtime the <classname>FilterChainProxy</classname> will
-    locate the first URI pattern that matches the current web request and the list
-    of filter beans specified by the <literal>filters</literal> attribute
-    will be applied to that request. The filters will be invoked in the order
-    they are defined, so you have complete control over the filter chain
-    which is applied to a particular URL.</para>
-
-    <para>You may have noticed we have declared two
-    <classname>HttpSessionContextIntegrationFilter</classname>s in the filter
-    chain (<literal>ASC</literal> is short for
-    <literal>allowSessionCreation</literal>, a property of
-    <classname>HttpSessionContextIntegrationFilter</classname>). As web
-    services will never present a <literal>jsessionid</literal> on future
-    requests, creating <literal>HttpSession</literal>s for such user
-    agents would be wasteful. If you had a high-volume application which
-    required maximum scalability, we recommend you use the approach shown
-    above. For smaller applications, using a single
-    <classname>HttpSessionContextIntegrationFilter</classname> (with its
-    default <literal>allowSessionCreation</literal> as
-    <literal>true</literal>) would likely be sufficient.</para>
-
-    <para>In relation to lifecycle issues, the
-    <classname>FilterChainProxy</classname> will always delegate
-    <literal>init(FilterConfig)</literal> and <literal>destroy()</literal>
-    methods through to the underlaying <literal>Filter</literal>s if such
-    methods are called against <classname>FilterChainProxy</classname> itself.
-    In this case, <classname>FilterChainProxy</classname> guarantees to only
-    initialize and destroy each <literal>Filter</literal> once,
-    irrespective of how many times it is declared by the
-    <interfacename>FilterInvocationDefinitionSource</interfacename>. You control the
-    overall choice as to whether these methods are called or not via the
-        <literal>targetFilterLifecycle</literal> initialization parameter of the
-        <literal>DelegatingFilterProxy</literal> that proxies
-        <literal>DelegatingFilterProxy</literal>. As discussed above, by default
-    any servlet container lifecycle invocations are not delegated through
-    to <literal>DelegatingFilterProxy</literal>.</para>
-
-    <para>You can use the attribute <literal>filters = "none"</literal>
-      in the same way that you do when using <link xlink:href="#namespace-auto-config">namespace configuration</link>
-      to build the <classname>FilterChainProxy</classname>. This will omit the
-      request pattern from the security filter chain entirely.
-       Note that anything matching this path will then have
-    no authentication or authorization services applied and will be freely
-    accessible.</para>
-
-    <para>The order that filters are defined in <literal>web.xml</literal>
+      </programlisting>        
+      The namespace element <literal>filter-chain-map</literal> is used to set up the security filter chain(s) which are required
+        within the application. It maps a particular URL pattern to a chain of filters built up from the bean names
+        specified in the <literal>filters</literal> element. Both regular
+        expressions and Ant Paths are supported, and the most specific URIs
+        appear first. At runtime the <classname>FilterChainProxy</classname> will
+        locate the first URI pattern that matches the current web request and the list
+        of filter beans specified by the <literal>filters</literal> attribute
+        will be applied to that request. The filters will be invoked in the order
+        they are defined, so you have complete control over the filter chain
+        which is applied to a particular URL.</para>
+      
+      <para>You may have noticed we have declared two
+        <classname>SecurityContextPersistenceFilter</classname>s in the filter
+        chain (<literal>ASC</literal> is short for
+        <literal>allowSessionCreation</literal>, a property of
+        <classname>SecurityContextPersistenceFilter</classname>). As web
+        services will never present a <literal>jsessionid</literal> on future
+        requests, creating <literal>HttpSession</literal>s for such user
+        agents would be wasteful. If you had a high-volume application which
+        required maximum scalability, we recommend you use the approach shown
+        above. For smaller applications, using a single
+        <classname>SecurityContextPersistenceFilter</classname> (with its
+        default <literal>allowSessionCreation</literal> as
+        <literal>true</literal>) would likely be sufficient.</para>
+      
+      <para>In relation to lifecycle issues, the
+        <classname>FilterChainProxy</classname> will always delegate
+        <methodname>init(FilterConfig)</methodname> and <methodname>destroy()</methodname>
+        methods through to the underlaying <interfacename>Filter</interfacename>s if such
+        methods are called against <classname>FilterChainProxy</classname> itself.
+        In this case, <classname>FilterChainProxy</classname> guarantees to only
+        initialize and destroy each <literal>Filter</literal> bean once,
+        no matter how many times it is declared in the filter chain(s). You control the
+        overall choice as to whether these methods are called or not via the
+        <literal>targetFilterLifecycle</literal> initialization parameter of
+        <literal>DelegatingFilterProxy</literal>. By default this property 
+        is <literal>false</literal> and servlet container lifecycle invocations are not delegated through
+        <literal>DelegatingFilterProxy</literal>.</para>
+      <para>
+        When we looked at how to set up web security using <link xlink:href="#namespace-auto-config">namespace configuration</link>,
+        we used a <literal>DelegatingFilterProxy</literal> with the name <quote>springSecurityFilterChain</quote>. You should now be able to 
+        see that this is the name of the <classname>FilterChainProxy</classname> which is created by the namespace.
+        </para>
+      <section>
+        <title>Bypassing the Filter Chain</title>
+        <para>
+         As with the namespace, you can use the attribute <literal>filters = "none"</literal> as an alternative to supplying a filter bean list.
+        This will omit the request pattern from the security filter chain entirely. Note that anything matching this path will then have
+        no authentication or authorization services applied and will be freely accessible.
+        </para>
+      </section>
+    </section>
+    
+    <section>
+      <title>Filter Ordering</title>
+    <para>The order that filters are defined in the chain
     is very important. Irrespective of which filters you are actually
-    using, the order of the <literal>&lt;filter-mapping&gt;</literal>s
-    should be as follows:</para>
+    using, the order should be as follows:
 
     <orderedlist inheritnum="ignore" continuation="restarts">
       <listitem>
-        <para><literal>ChannelProcessingFilter</literal>, because it might
+        <para><classname>ChannelProcessingFilter</classname>, because it might
         need to redirect to a different protocol</para>
       </listitem>
 
       <listitem>
-        <para><literal>ConcurrentSessionFilter</literal>, because it
+        <para><classname>ConcurrentSessionFilter</classname>, because it
         doesn't use any <classname>SecurityContextHolder</classname>
         functionality but needs to update the
         <interfacename>SessionRegistry</interfacename> to reflect ongoing requests
@@ -236,7 +150,7 @@
       </listitem>
 
       <listitem>
-        <para><classname>HttpSessionContextIntegrationFilter</classname>, so a
+        <para><classname>SecurityContextPersistenceFilter</classname>, so a
         <interfacename>SecurityContext</interfacename> can be setup in the
         <classname>SecurityContextHolder</classname> at the beginning of a web
         request, and any changes to the <interfacename>SecurityContext</interfacename>
@@ -246,10 +160,9 @@
 
       <listitem>
         <para>Authentication processing mechanisms -
-        <literal>UsernamePasswordAuthenticationProcessingFilter</literal>,
-        <literal>CasProcessingFilter</literal>,
-        <literal>BasicProcessingFilter, HttpRequestIntegrationFilter,
-        JbossIntegrationFilter</literal> etc - so that the
+        <classname>UsernamePasswordAuthenticationProcessingFilter</classname>,
+        <classname>CasProcessingFilter</classname>,
+        <classname>BasicProcessingFilter</classname> etc - so that the
         <classname>SecurityContextHolder</classname> can be modified to
         contain a valid <interfacename>Authentication</interfacename> request
         token</para>
@@ -274,7 +187,7 @@
       </listitem>
 
       <listitem>
-        <para><literal>AnonymousProcessingFilter</literal>, so that if no
+        <para><classname>AnonymousProcessingFilter</classname>, so that if no
         earlier authentication processing mechanism updated the
         <classname>SecurityContextHolder</classname>, an anonymous
         <interfacename>Authentication</interfacename> object will be put there</para>
@@ -292,21 +205,20 @@
         URIs</para>
       </listitem>
     </orderedlist>
-
-    <para>All of the above filters use
-    <literal>DelegatingFilterProxy</literal> or
-    <classname>FilterChainProxy</classname>. It is recommended that a single
-        <literal>DelegatingFilterProxy</literal> proxy through to a single
-    <classname>FilterChainProxy</classname> for each application, with that
-    <classname>FilterChainProxy</classname> defining all of Spring Security
-    filters.</para>
-
-    <para>If you're using SiteMesh, ensure Spring Security filters execute
-    before the SiteMesh filters are called. This enables the
-    <classname>SecurityContextHolder</classname> to be populated in time for
-    use by SiteMesh decorators</para>
+    </para>
   </section>
+      
+  <section>
+    <title>Use with other Filter-Based Frameworks</title>
+    <para>If you're using SiteMesh, ensure Spring Security filters execute
+      before the SiteMesh filters are called. This enables the
+      <classname>SecurityContextHolder</classname> to be populated in time for
+      use by SiteMesh decorators.</para>
+    
+  </section>    
   
+  
+  </section>
   <section xml:id="taglib">
     <info><title>Tag Libraries</title></info> 
 

+ 63 - 0
docs/manual/src/docbook/technical-overview.xml

@@ -580,4 +580,67 @@ Successfully authenticated. Security context contains: \
       </section>
     </section>
   </section>
+  <section xml:id="localization">
+    <title>Localization</title>
+    <para>Spring Security supports localization of exception messages that
+      end users are likely to see. If your application is designed for
+      English-speaking users, you don't need to do anything as by default all
+      Security Security messages are in English. If you need to support
+      other locales, everything you need to know is contained in this
+      section.</para>
+    
+    <para>All exception messages can be localized, including messages
+      related to authentication failures and access being denied
+      (authorization failures). Exceptions and logging that is focused on
+      developers or system deployers (including incorrect attributes,
+      interface contract violations, using incorrect constructors, startup
+      time validation, debug-level logging) etc are not localized and
+      instead are hard-coded in English within Spring Security's
+      code.</para>
+    
+    <para>Shipping in the <literal>spring-security-core-xx.jar</literal> you
+      will find an <literal>org.springframework.security</literal> package
+      that in turn contains a <literal>messages.properties</literal> file.
+      This should be referred to by your
+      <literal>ApplicationContext</literal>, as Spring Security classes
+      implement Spring's <literal>MessageSourceAware</literal> interface and
+      expect the message resolver to be dependency injected at application
+      context startup time. Usually all you need to do is register a bean
+      inside your application context to refer to the messages. An example
+      is shown below:</para>
+    
+    <para><programlisting><![CDATA[
+<bean id="messageSource" 
+    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
+  <property name="basename" value="org/springframework/security/messages"/>
+</bean>
+]]></programlisting></para>
+    
+    <para>The <literal>messages.properties</literal> is named in
+      accordance with standard resource bundles and represents the default
+      language supported by Spring Security messages. This default file is
+      in English. If you do not register a message source, Spring Security
+      will still work correctly and fallback to hard-coded English versions
+      of the messages.</para>
+    
+    <para>If you wish to customize the
+      <literal>messages.properties</literal> file, or support other
+      languages, you should copy the file, rename it accordingly, and
+      register it inside the above bean definition. There are not a large
+      number of message keys inside this file, so localization should not be
+      considered a major initiative. If you do perform localization of this
+      file, please consider sharing your work with the community by logging
+      a JIRA task and attaching your appropriately-named localized version
+      of <literal>messages.properties</literal>.</para>
+    
+    <para>Rounding out the discussion on localization is the Spring
+      <literal>ThreadLocal</literal> known as
+      <classname>org.springframework.context.i18n.LocaleContextHolder</classname>.
+      You should set the <classname>LocaleContextHolder</classname> to represent
+      the preferred <literal>Locale</literal> of each user. Spring Security
+      will attempt to locate a message from the message source using the
+      <literal>Locale</literal> obtained from this
+      <literal>ThreadLocal</literal>. Please refer to the Spring Framework documentation
+      for further details on using <literal>LocaleContextHolder</literal>.</para>
+  </section>  
 </chapter>