[seam-commits] Seam SVN: r8396 - trunk/doc/Seam_Reference_Guide/en-US.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Fri Jun 20 00:08:36 EDT 2008


Author: shane.bryzak at jboss.com
Date: 2008-06-20 00:08:36 -0400 (Fri, 20 Jun 2008)
New Revision: 8396

Modified:
   trunk/doc/Seam_Reference_Guide/en-US/Security.xml
Log:
work in progress

Modified: trunk/doc/Seam_Reference_Guide/en-US/Security.xml
===================================================================
--- trunk/doc/Seam_Reference_Guide/en-US/Security.xml	2008-06-19 20:14:32 UTC (rev 8395)
+++ trunk/doc/Seam_Reference_Guide/en-US/Security.xml	2008-06-20 04:08:36 UTC (rev 8396)
@@ -3,82 +3,54 @@
 <chapter id="security">
   <title>Security</title>
 
-  <para>
-    The Seam Security API is an optional Seam feature that provides authentication and authorization features
-    for securing both domain and page resources within your Seam project.
-  </para>
-
   <sect1>
     <title>Overview</title>
-
+    
     <para>
-      Seam Security provides two different modes of operation:
+      The Seam Security API provides a multitude of security-related features for your Seam-based application, covering 
+      such areas as:
     </para>
-
+    
     <itemizedlist>
       <listitem>
         <para>
-          <emphasis>simplified mode</emphasis> - this mode supports authentication services
-          and simple role-based security checks.
+          Authentication - an extensible, JAAS-based authentication layer that allows users to authenticate
+          against any security provider.
         </para>
       </listitem>
       <listitem>
         <para>
-          <emphasis>advanced mode</emphasis> - this mode supports all the same features as the simplified mode,
-          plus it offers rule-based security checks using JBoss Rules.
+          Identity Management - an API for managing a Seam application's users and roles at runtime.
         </para>
       </listitem>
-    </itemizedlist>
-
-    <sect2>
-      <title>Which mode is right for my application?</title>
-
-      <para>
-        That all depends on the requirements of your application.  If you have minimal security requirements, for example
-        if you only wish to restrict certain pages and actions to users who are logged in, or who belong to a certain role,
-        then the simplified mode will probably be sufficient.  The advantages of this is a more simplified configuration,
-        significantly less libraries to include, and a smaller memory footprint.
-      </para>
-
-      <para>
-        If on the other hand, your application requires security checks based on contextual state or complex business rules,
-        then you will require the features provided by the advanced mode.
-      </para>
-    </sect2>
-  </sect1>
-
-  <sect1>
-    <title>Requirements</title>
-
-    <para>
-      If using the advanced mode features of Seam Security, the following jar files are required to be configured as modules in
-      <literal>application.xml</literal>.  If you are using Seam Security in simplified mode, these are <emphasis>not</emphasis>
-      required:
-    </para>
-
-    <itemizedlist>
       <listitem>
-        <para>drools-compiler.jar</para>
+        <para>
+          Authorization - an extremely comprehensive authorization framework, supporting user roles, persistent and
+          rule-based permissions, and a pluggable permission resolver for easily implementing customised security logic.
+        </para>
       </listitem>
       <listitem>
-        <para>drools-core.jar</para>
+        <para>
+          Permission Management - a set of built-in Seam components to allow easy management of an application's 
+          security policy.
+        </para>   
       </listitem>
       <listitem>
-        <para>janino.jar</para>
+        <para>
+          CAPTCHA support - to assist in the prevention of automated software/scripts abusing your Seam-based site.
+        </para>
       </listitem>
       <listitem>
-        <para>antlr-runtime.jar</para>
+        <para>
+          And much more
+        </para>
       </listitem>
-      <listitem>
-        <para>mvel14.jar</para>
-      </listitem>
-    </itemizedlist>
-
+    </itemizedlist>                  
+    
     <para>
-      For web-based security, <literal>jboss-seam-ui.jar</literal> must also be included in the application's war file.
-    </para>
+      This chapter will cover each of these features in detail.
+    </para>    
 
-
   </sect1>
 
   <sect1>
@@ -105,7 +77,7 @@
       </listitem>
     </itemizedlist>
   </sect1>
-
+  
   <sect1>
     <title>Authentication</title>
 
@@ -114,17 +86,22 @@
       and as such provide a robust and highly configurable API for handling user authentication.  However, for less complex
       authentication requirements Seam offers a much more simplified method of authentication that hides the complexity of JAAS.
     </para>
-
+    
     <sect2>
-      <title>Configuration</title>
+      <title>Configuring an Authenticator component</title>
 
+      <note>
+        If you use Seam's Identity Management features (discussed later in this chapter) then it is not necessary to create
+        an authenticator component (and you can skip this section).
+      </note>
+
       <para>
-        The simplified authentication method uses a built-in JAAS login module, <literal>SeamLoginModule</literal>, which
+        The simplified authentication method provided by Seam uses a built-in JAAS login module, <literal>SeamLoginModule</literal>, which
         delegates authentication to one of your own Seam components.  This login module is already configured inside Seam as
         part of a default application policy and as such does not require any additional configuration files.  It allows you to
-        write an authentication method using the entity classes that are provided by your own application.  Configuring this
-        simplified form of authentication requires the <literal>identity</literal> component to be configured in
-        <literal>components.xml</literal>:
+        write an authentication method using the entity classes that are provided by your own application, or alternatively to 
+        authenticate against some other third party provider.  Configuring this simplified form of authentication requires the 
+        <literal>identity</literal> component to be configured in <literal>components.xml</literal>:
       </para>
 
       <programlisting role="XML"><![CDATA[<components xmlns="http://jboss.com/products/seam/components"
@@ -140,12 +117,6 @@
 </components>]]></programlisting>
 
       <para>
-        If you wish to use the advanced security features such as rule-based permission checks, all you need
-        to do is include the Drools (JBoss Rules) jars in your classpath, and add some additional configuration,
-        described later.
-      </para>
-
-      <para>
         The EL expression <literal>#{authenticator.authenticate}</literal> is a method binding indicating that
         the <literal>authenticate</literal> method of the <literal>authenticator</literal> component will be used
         to authenticate the user.
@@ -161,29 +132,31 @@
         <literal>components.xml</literal> specifies which method will be used by <literal>SeamLoginModule</literal>
         to authenticate users.  This method takes no parameters, and is expected to return a boolean indicating
         whether authentication is successful or not.  The user's username and password can be obtained from
-        <literal>Identity.instance().getUsername()</literal> and <literal>Identity.instance().getPassword()</literal>,
+        <literal>Credentials.getUsername()</literal> and <literal>Credentials.getPassword()</literal>,
         respectively.  Any roles that the user is a member of should be assigned using
-        <literal>Identity.instance().addRole()</literal>. Here's a complete example of an authentication method
-        inside a JavaBean component:
+        <literal>Identity.addRole()</literal>. Here's a complete example of an authentication method
+        inside a POJO component:
       </para>
 
       <programlisting role="JAVA"><![CDATA[@Name("authenticator")
 public class Authenticator {
    @In EntityManager entityManager;
+   @In Credentials credentials;
+   @In Identity identity;
 
    public boolean authenticate() {
       try
       {
          User user = (User) entityManager.createQuery(
             "from User where username = :username and password = :password")
-            .setParameter("username", Identity.instance().getUsername())
-            .setParameter("password", Identity.instance().getPassword())
+            .setParameter("username", credentials.getUsername())
+            .setParameter("password", credentials.getPassword())
             .getSingleResult();
 
          if (user.getRoles() != null)
          {
             for (UserRole mr : user.getRoles())
-               Identity.instance().addRole(mr.getName());
+               identity.addRole(mr.getName());
          }
 
          return true;
@@ -204,6 +177,16 @@
         In this case, if the user record is not found and a <literal>NoResultException</literal> thrown, the
         authentication method returns <literal>false</literal> to indicate the authentication failed.
       </para>
+      
+      <note>
+        When writing an authenticator method, it is important that it is kept minimal and free from
+        any side-effects. This is because there is no guarantee as to how many times the authenticator
+        method will be called by the security API, and as such it may be invoked multiple times during
+        a single request.  Because of this, any special code that should execute upon a successful or
+        failed authentication should be written by implementing an event observer.  See the section on
+        Security Events further down in this chapter for more information about which events are
+        raised by Seam Security.
+      </note>
 
       <sect3>
         <title>Identity.addRole()</title>
@@ -227,24 +210,19 @@
             <imagedata fileref="images/security-addrole.png" align="center"/>
           </imageobject>
         </mediaobject>
+        
+        <para>
+          If the current session is already authenticated, then calling <literal>Identity.addRole()</literal> will
+          have the expected effect of immediate granting the current user the specified role.
+        </para>
 
       </sect3>
 
       <sect3>
-        <title>Special Considerations</title>
+        <title>Writing an event observers for security-related events</title>
 
         <para>
-          When writing an authenticator method, it is important that it is kept minimal and free from
-          any side-effects. This is because there is no guarantee as to how many times the authenticator
-          method will be called by the security API, and as such it may be invoked multiple times during
-          a single request.  Because of this, any special code that should execute upon a successful or
-          failed authentication should be written by implementing an event observer.  See the section on
-          Security Events further down in this chapter for more information about which events are
-          raised by Seam Security.
-        </para>
-
-        <para>
-          To give an example, let's say that upon a successful login that some user statistics must be
+          Let's say for example that upon a successful login that some user statistics must be
           updated.  We would do this by writing an event observer for the
           <literal>org.jboss.seam.security.loginSuccessful</literal> event, like this:
         </para>
@@ -257,6 +235,11 @@
       userStats.setLastLoginDate(new Date());
       userStats.incrementLoginCount();
    }]]></programlisting>
+   
+        <para>
+          This observer method can be placed anywhere, even in the Authenticator component itself.
+          You can find more information about security-related events later in this chapter.
+        </para>
       </sect3>
 
     </sect2>
@@ -265,21 +248,21 @@
       <title>Writing a login form</title>
 
       <para>
-        The <literal>Identity</literal> component provides both <literal>username</literal> and <literal>password</literal>
+        The <literal>credentials</literal> component provides both <literal>username</literal> and <literal>password</literal>
         properties, catering for the most common authentication scenario. These properties can be bound directly to the
-        username and password fields on a login form.  Once these properties are set, calling the
-        <literal>identity.login()</literal> method will authenticate the user using the provided credentials.
+        username and password fields on a login form.  Once these properties are set, calling 
+        <literal>identity.login()</literal> will authenticate the user using the provided credentials.
         Here's an example of a simple login form:
       </para>
 
       <programlisting role="XHTML"><![CDATA[<div>
     <h:outputLabel for="name" value="Username"/>
-    <h:inputText id="name" value="#{identity.username}"/>
+    <h:inputText id="name" value="#{credentials.username}"/>
 </div>
 
 <div>
     <h:outputLabel for="password" value="Password"/>
-    <h:inputSecret id="password" value="#{identity.password}"/>
+    <h:inputSecret id="password" value="#{credentials.password}"/>
 </div>
 
 <div>
@@ -288,13 +271,13 @@
 
       <para>
         Similarly, logging out the user is done by calling <literal>#{identity.logout}</literal>. Calling this
-        action will clear the security state of the currently authenticated user.
+        action will clear the security state of the currently authenticated user, and invalidate the user's session.
       </para>
 
     </sect2>
 
     <sect2>
-      <title>Simplified Configuration - Summary</title>
+      <title>Configuration Summary</title>
       <para>
         So to sum up, there are the three easy steps to configure authentication:
       </para>
@@ -509,9 +492,653 @@
           itself using the configured JAAS security policy.
         </para>
       </sect3>
+    </sect2>
+  </sect1>
+  
+  <sect1>
+    <title>Identity Management</title>
+    
+    <para>
+      Identity Management provides a standard API for the management of a Seam application's users and roles,
+      regardless of which identity store (database, LDAP, etc) is used on the backend.  At the center
+      of the Identity Management API is the <literal>identityManager</literal> component, which provides 
+      all the methods for creating, modifying and deleting users, granting and revoking roles, changing passwords,
+      enabling and disabling user accounts, authenticating users and listing users and roles.
+    </para>
+    
+    <sect2>
+      <title>Configuring IdentityManager</title>
+      
+      <para>    
+        The <literal>identityManager</literal> component allows for separate identity stores to be configured 
+        for authentication and authorization operations.  This means that it is possible for users to
+        be authenticated against one identity store, for example an LDAP directory, yet have their roles 
+        loaded from another identity store, such as a relational database.
+      </para>
+      
+      <para>
+        Seam provides two <literal>IdentityStore</literal> implementations out of the box; 
+        <literal>JpaIdentityStore</literal> uses a relational database to store user and role information, 
+        and is the default identity store that is used if nothing is explicitly configured in the
+        <literal>identityManager</literal> component.  The other implementation that is provided is 
+        <literal>LdapIdentityStore</literal>, which uses an LDAP directory to store users and roles.
+      </para>
+      
+      <para>
+        There are two configurable properties for the <literal>identityManager</literal> component - 
+        <literal>identityStore</literal> and <literal>roleIdentityStore</literal>.  The value for these
+        properties must be an EL expression referring to a Seam component implementing the
+        <literal>IdentityStore</literal> interface.  As already mentioned,
+        if left unconfigured then <literal>JpaIdentityStore</literal> will be assumed by default.  If
+        only the <literal>identityStore</literal> property is configured, then the same value will be used for
+        <literal>roleIdentityStore</literal> also.  For example, the following entry in
+        <literal>components.xml</literal> will configure <literal>identityManager</literal> to use
+        an <literal>LdapIdentityStore</literal> for both user-related and role-related operations:
+      </para>
 
+      <programlisting><![CDATA[      
+  <security:identity-manager identity-store="#{ldapIdentityStore}"/>
+      ]]></programlisting>
+      
+      <para>
+        The following example configures <literal>identityManager</literal> to use an <literal>LdapIdentityStore</literal>
+        for user-related operations, and <literal>JpaIdentityStore</literal> for role-related operations:
+      </para>
+      
+      <programlisting><![CDATA[      
+  <security:identity-manager 
+    identity-store="#{ldapIdentityStore}" 
+    role-identity-store="#{jpaIdentityStore}"/>
+      ]]></programlisting>
+      
+      <para>
+        The following sections explain both of these identity store implementations in greater detail.
+      </para>
+      
     </sect2>
+    
+    <sect2>
+      <title>JpaIdentityStore</title>
+      
+      <para>
+        This identity store allows for users and roles to be stored inside a relational database.  It is designed 
+        to be as unrestrictive as possible in regards to database schema design, allowing a great deal of 
+        flexibility in the underlying table structure.  This is achieved through the use of a set of special
+        annotations, allowing entity beans to be configured to store user and role records.  
+      </para>
+      
+      <sect3>
+        <title>Configuring JpaIdentityStore</title>
+        
+        <para>
+          <literal>JpaIdentityStore</literal> requires that both the <literal>user-class</literal> and 
+          <literal>role-class</literal> properties are configured.  These properties should refer to the
+          entity classes that are to be used to store both user and role records, respectively.  The following
+          example shows the configuration from <literal>components.xml</literal> in the SeamSpace example:
+        </para>
+        
+        <programlisting><![CDATA[
+  <security:jpa-identity-store 
+    user-class="org.jboss.seam.example.seamspace.MemberAccount"
+    role-class="org.jboss.seam.example.seamspace.MemberRole"/>
+        ]]></programlisting>
+        
+      </sect3>
+      
+      <sect3>
+        <title>Configuring the Entities</title>
+        
+        <para>
+          As already mentioned, a set of special annotations are used to configure entity beans for storing
+          users and roles.  The following table lists each of the annotations, and their descriptions.
+        </para>
+        
+        <table>
+          <title>User Entity Annotations</title>
+    
+          <tgroup cols="2">
+            <colspec colnum="1" colwidth="2*" />
+            <colspec colnum="2" colwidth="1*" />
+            <colspec colnum="3" colwidth="3*" />
+    
+            <thead>
+              <row>
+                <entry align="center">
+                  <para>Annotation</para>
+                </entry>
+                <entry align="center">
+                  <para>Status</para>
+                </entry>
+                <entry align="center">
+                  <para>Description</para>
+                </entry>
+              </row>
+            </thead>
+    
+            <tbody>    
+              <row>
+                <entry>
+                  <para>
+                    <literal>@UserPrincipal</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Required</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the user's username.
+                  </para>
+                </entry>
+              </row> 
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>@UserPassword</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Required</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the user's password.  It allows a <literal>hash</literal>
+                    algorithm to be specified for password hashing.  Possible values for <literal>hash</literal> are
+                    <literal>md5</literal> and <literal>sha</literal>.  E.g:
+                    
+                    <programlisting><![CDATA[@UserPassword(hash = "md5")
+public String getPasswordHash() { 
+  return passwordHash; 
+}]]></programlisting>
+                    
+                  </para>
+                </entry>
+              </row>     
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>@UserFirstName</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Optional</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the user's first name.
+                  </para>
+                </entry>
+              </row> 
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>@UserLastName</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Optional</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the user's last name.
+                  </para>
+                </entry>
+              </row>   
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>@UserEnabled</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Optional</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the enabled status of the user.  This should be a boolean
+                    property, and if not present then all user accounts are assumed to be enabled.
+                  </para>
+                </entry>
+              </row>    
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>@UserRoles</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Required</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the roles of the user.  This property will be described in 
+                    more detail further down.
+                  </para>
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </table>               
+              
+        <table>
+          <title>Role Entity Annotations</title>
+    
+          <tgroup cols="2">
+            <colspec colnum="1" colwidth="2*" />
+            <colspec colnum="2" colwidth="1*" />
+            <colspec colnum="3" colwidth="3*" />
+    
+            <thead>
+              <row>
+                <entry align="center">
+                  <para>Annotation</para>
+                </entry>
+                <entry align="center">
+                  <para>Status</para>
+                </entry>
+                <entry align="center">
+                  <para>Description</para>
+                </entry>
+              </row>
+            </thead>
+    
+            <tbody>               
+              <row>
+                <entry>
+                  <para>
+                    <literal>@RoleName</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Required</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the name of the role.
+                  </para>
+                </entry>
+              </row>  
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>@RoleGroups</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Optional</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method containing the group memberships of the role.
+                  </para>
+                </entry>
+              </row>    
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>@RoleConditional</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>Optional</para>
+                </entry>
+                <entry>
+                  <para>
+                    This annotation marks the field or method indicating whether the role is conditional or not.
+                    Conditional roles are explained later in this chapter.
+                  </para>
+                </entry>
+              </row>                                                                                       
+              
+            </tbody>
+          </tgroup>
+        </table>     
+        
+      </sect3>
+      
+      <sect3>
+        <title>Entity Bean Examples</title>
+        
+        <para>
+          As mentioned previously, <literal>JpaIdentityStore</literal> is designed to be as flexible as possible when
+          it comes to the database schema design of your user and role tables.  This section looks at a number of
+          possible database schemas that can be used to store user and role records.
+        </para>
+        
+        <sect4>
+          <title>Minimal schema example</title>
+          
+          <para>
+            In this bare minimal example, a simple user and role table are linked via a
+            many-to-many relationship using a cross-reference table named <literal>UserRoles</literal>.
+          </para>
+          
+          <mediaobject>
+            <imageobject role="fo">
+              <imagedata fileref="images/security-entities-1.png" align="center" scalefit="1"/>
+            </imageobject>
+            <imageobject role="html">
+              <imagedata fileref="images/security-entities-1.png" align="center"/>
+            </imageobject>
+          </mediaobject>          
+          
+          <programlisting><![CDATA[@Entity
+public class User {
+  private Integer userId;
+  private String username;
+  private String passwordHash;
+  private Set<Role> roles;
+  
+  @Id @GeneratedValue
+  public Integer getUserId() { return userId; }
+  public void setUserId(Integer userId) { this.userId = userId; }
+  
+  @UserPrincipal
+  public String getUsername() { return username; }
+  public void setUsername(String username) { this.username = username; }
+  
+  @UserPassword(hash = "md5")
+  public String getPasswordHash() { return passwordHash; }
+  public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
+  
+  @UserRoles
+  @ManyToMany(targetEntity = Role.class)
+  @JoinTable(name = "UserRoles", 
+    joinColumns = @JoinColumn(name = "UserId"),
+    inverseJoinColumns = @JoinColumn(name = "RoleId"))
+  public Set<Role> getRoles() { return roles; }
+  public void setRoles(Set<Role> roles) { this.roles = roles; }
+}]]></programlisting>
+<programlisting><![CDATA[@Entity
+public class Role {
+  private Integer roleId;
+  private String rolename;
+  
+  @Id @Generated
+  public Integer getRoleId() { return roleId; }
+  public void setRoleId(Integer roleId) { this.roleId = roleId; }
+  
+  @RoleName
+  public String getRolename() { return rolename; }
+  public void setRolename(String rolename) { this.rolename = rolename; }
+}]]></programlisting>
 
+        </sect4>
+        
+        <sect4>
+          <title>Complex Schema Example</title>
+          
+          <para>
+            This example builds on the above minimal example by including all of the optional fields, and allowing
+            group memberships for roles.
+          </para>
+          
+          <mediaobject>
+            <imageobject role="fo">
+              <imagedata fileref="images/security-entities-2.png" align="center" scalefit="1"/>
+            </imageobject>
+            <imageobject role="html">
+              <imagedata fileref="images/security-entities-2.png" align="center"/>
+            </imageobject>
+          </mediaobject>         
+          
+          <programlisting><![CDATA[@Entity
+public class User {
+  private Integer userId;
+  private String username;
+  private String passwordHash;
+  private Set<Role> roles;
+  private String firstname;
+  private String lastname;
+  private boolean enabled;
+  
+  @Id @GeneratedValue
+  public Integer getUserId() { return userId; }
+  public void setUserId(Integer userId) { this.userId = userId; }
+  
+  @UserPrincipal
+  public String getUsername() { return username; }
+  public void setUsername(String username) { this.username = username; }
+  
+  @UserPassword(hash = "md5")
+  public String getPasswordHash() { return passwordHash; }
+  public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
+  
+  @UserFirstName
+  public String getFirstname() { return firstname; }
+  public void setFirstname(String firstname) { this.firstname = firstname; }
+  
+  @UserLastName
+  public String getLastname() { return lastname; }
+  public void setLastname(String lastname) { this.lastname = lastname; }
+  
+  @UserEnabled
+  public boolean isEnabled() { return enabled; }
+  public void setEnabled(boolean enabled) { this.enabled = enabled; }
+  
+  @UserRoles
+  @ManyToMany(targetEntity = Role.class)
+  @JoinTable(name = "UserRoles", 
+    joinColumns = @JoinColumn(name = "UserId"),
+    inverseJoinColumns = @JoinColumn(name = "RoleId"))
+  public Set<Role> getRoles() { return roles; }
+  public void setRoles(Set<Role> roles) { this.roles = roles; }
+}]]></programlisting>
+<programlisting><![CDATA[@Entity
+public class Role {
+  private Integer roleId;
+  private String rolename;
+  private boolean conditional;
+  
+  @Id @Generated
+  public Integer getRoleId() { return roleId; }
+  public void setRoleId(Integer roleId) { this.roleId = roleId; }
+  
+  @RoleName
+  public String getRolename() { return rolename; }
+  public void setRolename(String rolename) { this.rolename = rolename; }
+  
+  @RoleConditional
+  public boolean isConditional() { return conditional; }
+  public void setConditional(boolean conditional) { this.conditional = conditional; }
+  
+  @RoleGroups
+  @ManyToMany(targetEntity = Role.class)
+  @JoinTable(name = "RoleGroups", 
+    joinColumns = @JoinColumn(name = "RoleId"),
+    inverseJoinColumns = @JoinColumn(name = "GroupId"))
+  public Set<Role> getGroups() { return groups; }
+  public void setGroups(Set<Role> groups) { this.groups = groups; }  
+  
+}]]></programlisting>           
+        </sect4>
+      
+      </sect3>
+      
+      <sect3>
+        <title>JpaIdentityStore Events</title>
+        
+        <para>
+          When using <literal>JpaIdentityStore</literal> as the identity store implementation with <literal>IdentityManager</literal>,
+          a few events are raised as a result of invoking certain <literal>IdentityManager</literal> methods.
+        </para>
+        
+        <sect4>
+          <title>JpaIdentityStore.EVENT_PRE_PERSIST_USER</title>
+          
+          <para>
+            This event is raised in response to calling <literal>IdentityManager.createUser()</literal>.  Just before the user
+            entity is persisted to the database, this event will be raised passing the entity instance as an event parameter.  
+            The entity will be an instance of the <literal>user-class</literal> configured for <literal>JpaIdentityStore</literal>.            
+          </para>
+          
+          <para>
+            Writing an observer for this event may be useful for setting additional field values on the entity, which aren't set
+            as part of the standard <literal>createUser()</literal> functionality.
+          </para>
+        </sect4>
+        
+        <sect4>
+          <title>JpaIdentityStore.EVENT_USER_CREATED</title>
+          
+          <para>
+            This event is also raised in response to calling <literal>IdentityManager.createUser()</literal>.  However, it is 
+            raised after the user entity has already been persisted to the database.  Like the <literal>EVENT_PRE_PERSIST_USER</literal>
+            event, it also passes the entity instance as an event parameter.  It may be useful to observe this event if you also
+            need to persist other entities that reference the user entity, for example contact detail records or other user-specific
+            data.
+          </para>
+        </sect4>
+        
+        <sect4>
+          <title>JpaIdentityStore.EVENT_USER_AUTHENTICATED</title>
+          
+          <para>
+            This event is raised when calling <literal>IdentityManager.authenticate()</literal>.  It passes the user entity instance
+            as the event parameter, and is useful for reading additional properties from the user entity that is being authenticated.
+          </para>
+        </sect4>
+      </sect3>
+      
+    </sect2>
+    
+    <sect2>
+      <title>LdapIdentityStore</title>
+      
+      <para>
+        This identity store implementation is designed for working with user records stored in an LDAP directory.  It is very
+        highly configurable, allowing great flexibility in how both users and roles are stored in the directory.  The following
+        sections describe the configuration options for this identity store, and provide some configuration examples.
+      </para>
+      
+      <sect3>
+        <title>Configuring LdapIdentityStore</title>
+        
+        <para>
+          The following table describes the available properties that can be configured in <literal>components.xml</literal> for
+          <literal>LdapIdentityStore</literal>.
+        </para>
+        
+        <table>
+          <title>LdapIdentityStore Configuration Properties</title>
+    
+          <tgroup cols="2">
+            <colspec colnum="1" colwidth="2*" />
+            <colspec colnum="2" colwidth="3*" />
+    
+            <thead>
+              <row>
+                <entry align="center">
+                  <para>Property</para>
+                </entry>
+                <entry align="center">
+                  <para>Description</para>
+                </entry>
+              </row>
+            </thead>
+    
+            <tbody>               
+              <row>
+                <entry>
+                  <para>
+                    <literal>server-address</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>
+                    The address of the LDAP server, defaults to <literal>localhost</literal>.
+                  </para>
+                </entry>
+              </row>
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>server-port</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>
+                    The port number that the LDAP server is listening on, defaults to 389.
+                  </para>
+                </entry>
+              </row>
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>user-context-DN</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>
+                    The Distinguished Name (DN) of the context containing user records.  The default value is
+                    "<literal>ou=Person,dc=acme,dc=com</literal>".
+                  </para>
+                </entry>
+              </row>
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>user-DN-prefix</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>
+                    This value is prefixed to the front of the username to locate the user's record.
+                    The default value is "<literal>uid=</literal>".
+                  </para>
+                </entry>
+              </row>
+              
+              <row>
+                <entry>
+                  <para>
+                    <literal>user-DN-suffix</literal>
+                  </para>
+                </entry>
+                <entry>
+                  <para>
+                    This value is appended to the end of the username to locate the user's record.  The default
+                    value is "<literal>,ou=Person,dc=acme,dc=com</literal>".
+                  </para>
+                </entry>
+              </row>
+               
+            </tbody>
+          </tgroup>
+        </table>     
+      </sect3>
+    </sect2>
+    
+    <sect2>
+      <title>Writing your own IdentityStore implementation</title>
+      
+      <para>
+      
+      </para>
+    </sect2>
+    
+    <sect2>
+      <title>Authentication with Identity Management</title>
+      
+      <para>
+        If you are using the Identity Management features in your Seam application, then it is not required
+        to provide an authenticator component (see previous Authentication section) to enable authentication.
+        Simply omit the <literal>authenticator-method</literal> from the <literal>identity</literal> configuration
+        in <literal>components.xml</literal>, and the <literal>SeamLoginModule</literal> will by default
+        use <literal>IdentityManager</literal> to authenticate your application's users, without any special
+        configuration required.
+      </para>
+    </sect2>
   </sect1>
 
   <sect1>
@@ -1028,7 +1655,46 @@
       </sect3>
 
     </sect2>
+    
 
+    <sect2>
+      <title>Rule-based Permissions</title>
+      
+      <sect3>
+        <title>Configuration</title>
+        
+      </sect3>
+
+      <sect3>
+        <title>Requirements</title>
+    
+        <para>
+          If using the rule-based permission features provided by Seam Security, the following jar files are required to be 
+          distributed with your project:
+        </para>
+    
+        <itemizedlist>
+          <listitem>
+            <para>drools-compiler.jar</para>
+          </listitem>
+          <listitem>
+            <para>drools-core.jar</para>
+          </listitem>
+          <listitem>
+            <para>janino.jar</para>
+          </listitem>
+          <listitem>
+            <para>antlr-runtime.jar</para>
+          </listitem>
+          <listitem>
+            <para>mvel14.jar</para>
+          </listitem>
+        </itemizedlist>
+    
+      </sect3>    
+      
+    </sect2>
+
   </sect1>
 
   <sect1>
@@ -1666,7 +2332,7 @@
         <imagedata fileref="images/security-identitymanager.png" align="center"/>
       </imageobject>
       <imageobject role="html">
-        <imagedata fileref="../shared/images/security-identitymanager.png" align="center"/>
+        <imagedata fileref="images/security-identitymanager.png" align="center"/>
       </imageobject>
     </mediaobject>
 
@@ -1702,7 +2368,7 @@
           <imagedata fileref="images/security-useraccount.png" align="center"/>
         </imageobject>
         <imageobject role="html">
-          <imagedata fileref="../shared/images/security-useraccount.png" align="center"/>
+          <imagedata fileref="images/security-useraccount.png" align="center"/>
         </imageobject>
       </mediaobject>
 
@@ -1715,7 +2381,7 @@
           <imagedata fileref="images/security-useraccountschema.png" align="center"/>
         </imageobject>
         <imageobject role="html">
-          <imagedata fileref="../shared/images/security-useraccountschema.png" align="center"/>
+          <imagedata fileref="images/security-useraccountschema.png" align="center"/>
         </imageobject>
       </mediaobject>
 
@@ -2515,7 +3181,7 @@
           <imagedata fileref="images/security-usermanager1.png" align="center"/>
         </imageobject>
         <imageobject role="html">
-          <imagedata fileref="../shared/images/security-usermanager1.png" align="center"/>
+          <imagedata fileref="images/security-usermanager1.png" align="center"/>
         </imageobject>
       </mediaobject>
 
@@ -2528,7 +3194,7 @@
           <imagedata fileref="images/security-usermanager2.png" align="center"/>
         </imageobject>
         <imageobject role="html">
-          <imagedata fileref="../shared/images/security-usermanager2.png" align="center"/>
+          <imagedata fileref="images/security-usermanager2.png" align="center"/>
         </imageobject>
       </mediaobject>
 




More information about the seam-commits mailing list