From do-not-reply at jboss.org Fri Jul 30 11:13:45 2010
Content-Type: multipart/mixed; boundary="===============0903027441959976257=="
MIME-Version: 1.0
From: do-not-reply at jboss.org
To: exo-jcr-commits at lists.jboss.org
Subject: [exo-jcr-commits] exo-jcr SVN: r2846 - in
jcr/branches/1.12.x/docs/reference/en/src/main: docbook/en-US/modules/core
and 1 other directories.
Date: Fri, 30 Jul 2010 11:13:45 -0400
Message-ID: <201007301513.o6UFDjSu005372@svn01.web.mwc.hst.phx2.redhat.com>
--===============0903027441959976257==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Author: dkatayev
Date: 2010-07-30 11:13:44 -0400 (Fri, 30 Jul 2010)
New Revision: 2846
Added:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/conversationstate-when-membership-changed.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/db-configuration-hibernate.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/db-schema-creator-service.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/ldap-configuration.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/organization-service-initalizer.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/organization-service-listener.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/organization-service.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/security-service.xml
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e/spring-security-integration.xml
jcr/branches/1.12.x/docs/reference/en/src/main/resources/images/login-pa=
ge.jpg
jcr/branches/1.12.x/docs/reference/en/src/main/resources/images/organiza=
tion-exo.jpg
Modified:
jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/cor=
e.xml
Log:
EXOJCR-868 core documentation added
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/conversationstate-when-membership-changed.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/conversationstate-when-membership-changed.xml (r=
ev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/conversationstate-when-membership-changed.xml 2010-07-30 15:13:44 UTC (r=
ev 2846)
@@ -0,0 +1,34 @@
+
+
+
+ Update ConversationState when user's Membership changed
+
+ When user logged in portal in ConversationRegistry added
+ ConversationSate for this user. ConversationState keeps user's Identity =
that
+ is actual for logged in time. In this case even user's Membership update=
d in
+ OrganizationService ConversationState still keeps old (not actual Identi=
ty).
+ User must logged out and loggin in again to update Identity. To fix this
+ issue need add special listener in configuration of OrganizationServicer.
+ This listener is extended MembershipEventListener.
+
+ Example of configuration.
+
+ <?xml version=3D"1.0" encoding=3D"ISO-8859-1"?>
+<configuration
+ xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=3D"http://www.exoplaform.org/xml/ns/kernel_1_0.xsd h=
ttp://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns=3D"http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <target-component>org.exoplatform.services.organization.Organiza=
tionService</target-component>
+.....
+.....
+ <component-plugin>
+ <name>MembershipUpdateListener</name>
+ <set-method>addListenerPlugin</set-method>
+ <type>org.exoplatform.services.organization.impl.MembershipUpd=
ateListener</type>
+ </component-plugin>
+
+ <external-component-plugins>
+</configuration>
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/db-configuration-hibernate.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/db-configuration-hibernate.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/db-configuration-hibernate.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,115 @@
+
+
+
+ Database Configuration for Hibernate
+
+ As usual, it is quite simple to use our configuration XML syntax to
+ configure and parametrize different Databases for eXo tables but also for
+ your own use.
+
+
+ Generic configuration
+
+ The default DB configuration uses HSQLDB, a Java Database quite
+ useful for demonstrations.
+
+ <component> =
+ <key>org.exoplatform.services.database.HibernateService</key&g=
t;
+ <jmx-name>exo-service:type=3DHibernateService</jmx-name>
+ <type>org.exoplatform.services.database.impl.HibernateServiceImpl=
</type>
+ <init-params>
+ <properties-param>
+ <name>hibernate.properties</name>
+ <description>Default Hibernate Service</description>
+ <property name=3D"hibernate.show_sql" value=3D"false"/>
+ <property name=3D"hibernate.cglib.use_reflection_optimizer" va=
lue=3D"true"/>
+ <property name=3D"hibernate.connection.url" value=3D"jdbc:hsql=
db:file:../temp/data/portal"/>
+ <property name=3D"hibernate.connection.driver_class" value=3D"=
org.hsqldb.jdbcDriver"/>
+ <property name=3D"hibernate.connection.autocommit" value=3D"tr=
ue"/>
+ <property name=3D"hibernate.connection.username" value=3D"sa"/=
>
+ <property name=3D"hibernate.connection.password" value=3D""/&g=
t;
+ <property name=3D"hibernate.dialect" value=3D"org.hibernate.di=
alect.HSQLDialect"/>
+ <property name=3D"hibernate.c3p0.min_size" value=3D"5"/>
+ <property name=3D"hibernate.c3p0.max_size" value=3D"20"/>
+ <property name=3D"hibernate.c3p0.timeout" value=3D"1800"/>
+ <property name=3D"hibernate.c3p0.max_statements" value=3D"50"/=
>
+ </properties-param>
+ </init-params>
+</component>
+
+ In the init parameter section, we define the default hibernate
+ properties including the DB URL, the driver and the credentials in
+ use.
+
+ As for any portal that configuration can be overridden depending=
on
+ the needs of your environment.
+
+ Several databases have been tested and can be used in
+ production....which is not the case of HSQLDB, HSQLDB can only be used=
for
+ development environments and for demonstrations.
+
+
+
+ Example DB configuration
+
+ For MySQL
+
+ <component> =
+ <key>org.exoplatform.services.database.HibernateService</key&g=
t;
+ <jmx-name>database:type=3DHibernateService</jmx-name>
+ <type>org.exoplatform.services.database.impl.HibernateServiceImpl=
</type>
+ <init-params>
+ <properties-param>
+ <name>hibernate.properties</name>
+ <description>Default Hibernate Service</description>
+ <property name=3D"hibernate.show_sql" value=3D"false"/>
+ <property name=3D"hibernate.cglib.use_reflection_optimizer" va=
lue=3D"true"/>
+ <property name=3D"hibernate.connection.url" value=3D"jdbc:mysq=
l://localhost:3306/exodb?relaxAutoCommit=3Dtrue&amp;autoReconnect=
=3Dtrue&amp;useUnicode=3Dtrue&amp;characterEncoding=3Dutf8"=
/>
+ <property name=3D"hibernate.connection.driver_class" value=3D"=
com.mysql.jdbc.Driver"/>
+ <property name=3D"hibernate.connection.autocommit" value=3D"tr=
ue"/>
+ <property name=3D"hibernate.connection.username" value=3D"exo"=
/>
+ <property name=3D"hibernate.connection.password" value=3D"exo"=
/>
+ <property name=3D"hibernate.dialect" value=3D"org.hibernate.di=
alect.MySQLDialect"/>
+ <property name=3D"hibernate.c3p0.min_size" value=3D"5"/>
+ <property name=3D"hibernate.c3p0.max_size" value=3D"20"/>
+ <property name=3D"hibernate.c3p0.timeout" value=3D"1800"/>
+ <property name=3D"hibernate.c3p0.max_statements" value=3D"50"/=
>
+ </properties-param>
+ </init-params>
+</component>
+
+
+
+ Register custom Hibernate XML files into the service
+
+ It is possible to use the eXo hibernate service and register your
+ hibernate hbm.xml files to leverage some add-on features of the service
+ such as the table automatic creation as well as the cache of the hiber=
nate
+ session in a ThreadLocal object during all the request lifecycle. To d=
o so
+ you just have to add a plugin and indicate the location of your
+ files.
+
+ <?xml version=3D"1.0" encoding=3D"ISO-8859-1"?>
+<configuration>
+ <external-component-plugins>
+ <target-component>org.exoplatform.services.database.HibernateSer=
vice</target-component>
+ <component-plugin> =
+ <name>add.hibernate.mapping</name>
+ <set-method>addPlugin</set-method>
+ <type>org.exoplatform.services.database.impl.AddHibernateMappi=
ngPlugin</type>
+ <init-params>
+ <values-param>
+ <name>hibernate.mapping</name>
+ <value>org/exoplatform/services/organization/impl/UserImpl=
.hbm.xml</value>
+ <value>org/exoplatform/services/organization/impl/Membersh=
ipImpl.hbm.xml</value>
+ <value>org/exoplatform/services/organization/impl/GroupImp=
l.hbm.xml</value>
+ <value>org/exoplatform/services/organization/impl/Membersh=
ipTypeImpl.hbm.xml</value>
+ <value>org/exoplatform/services/organization/impl/UserProf=
ileData.hbm.xml</value>
+ </values-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins> =
+</configuration>
+
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/db-schema-creator-service.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/db-schema-creator-service.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/db-schema-creator-service.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,48 @@
+
+
+
+ DB Schema creator service (JDBC implementation)
+
+ DB Schema Creator is responsible for database schema creating usin=
g a
+ DDL script inside service configuration or in an external file,
+ calling:
+
+ org.exoplatform.services.database.jdbc.DBSchemaCreator=
.createTables(String dsName, String script)
+
+ via
+
+ org.exoplatform.services.database.jdbc.CreateDBSchemaPlu=
gin component plugin
+
+ A configuration example:
+
+ <component>
+ <key>org.exoplatform.services.database.jdbc.DBSchemaCreator</k=
ey>
+ <type>org.exoplatform.services.database.jdbc.DBSchemaCreator</=
type>
+ <component-plugins> =
+ <component-plugin> =
+ <name>jcr.dbschema</name>
+ <set-method>addPlugin</set-method>
+ <type>org.exoplatform.services.database.jdbc.CreateDBSchema=
Plugin</type>
+ <init-params>
+ <value-param>
+ <name>data-source</name>
+ <value>jdbcjcr</value>
+ </value-param>
+ <value-param>
+ <name>script-file</name>
+ <value>conf/storage/jcr-mjdbc.sql</value>
+ </value-param> =
+ </init-params> =
+ </component-plugin>
+ ........
+
+ An example of a DDL script:
+
+ CREATE TABLE JCR_MITEM(
+ ID VARCHAR(255) NOT NULL PRIMARY KEY, =
+ VERSION INTEGER NOT NULL, =
+ PATH VARCHAR(1024) NOT NULL
+ );
+CREATE INDEX JCR_IDX_MITEM_PATH ON JCR_MITEM(PATH);
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/ldap-configuration.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/ldap-configuration.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/ldap-configuration.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,849 @@
+
+
+
+ LDAP Configuration
+
+
+ Overview
+
+ You may decide that you want eXo users to be mapped to an existi=
ng
+ directory. eXo provides a flexible implementation of its
+ OrganizationService on top of LDAP. It can be used on any LDAP complia=
nt
+ directory and even Active Directory. This page will guide you how to
+ configure eXo Platform to work with your directory.
+
+
+
+ Quickstart
+
+ If you just want to have a look at how eXo works with ldap. eXo
+ comes with a predefined ldap configuration. You just need to activate =
it
+ and eXo will create all it needs to work at startup.
+
+ You need to have a working ldap server and a user with write
+ permissions.
+
+
+
+ Open exo-tomcat/webapps/portal/WEB-INF/conf/configuration=
.xml
+ and replace:
+
+
+
+ <import>war:/conf/organization/hibernate-configu=
ration.xml</import>
+
+ With
+
+ <import>war:/conf/organization/ldap-configuratio=
n.xml</import>
+
+
+
+ 0pen ldap-configuration.xml and
+ update the providerURL, rootdn and password settings according to=
your
+ environment
+
+
+
+ <field name=3D"providerURL"><string>ldap:/=
/127.0.0.1:389</string></field>
+<field name=3D"rootdn"><string>CN=3DManager,DC=3DMyCompany,DC=
=3Dcom</string></field>
+<field name=3D"password"><string>secret</string></fie=
ld>
+
+
+
+ Delete exo-tomcat/temp/* =
to
+ have a clean database and then start tomcat.
+
+
+
+ eXo starts and autocreates its organization model in your direct=
ory
+ tree. Finally the structure of the default LDAP schema looks like:
+
+
+
+
+
+
+
+ That's it! Now eXo uses your LDAP directory as its org model
+ storage. Users, groups and memberships are now stored and retrieved fr=
om
+ there. We suggest that you complete some guideline functions with eXo =
user
+ management portlet and see what it changes in your directory tree.
+
+
+
+ Configuration
+
+ If you have an existing LDAP server, the eXo predefined settings
+ will likely not match your directory structure. eXo LDAP organization
+ service implementation was written with flexibility in mind and can
+ certainly be configured to meet your requirements.
+
+ The configuration is done in ldap-configuration.xml file, and this chapter=
will
+ explain the numerous parameters it contains.
+
+
+ Connection Settings
+
+ Firstly, start by connection settings which will tell eXo how =
to
+ connect to your directory server. These settings are very close to
+ JNDI
+ API>http://java.sun.com/products/jndi context parameters.
+ This configuration is activated by the init-param ldap.config of ser=
vice
+ LDAPServiceImpl.
+
+ <component>
+ <key>org.exoplatform.services.ldap.LDAPService</key>
+ <type>org.exoplatform.services.ldap.impl.LDAPServiceImpl</type&=
gt;
+ <init-params>
+ <object-param>
+ <name>ldap.config</name>
+ <description>Default ldap config</description>
+ <object type=3D"org.exoplatform.services.ldap.impl.LDAPConnection=
Config">
+ <field name=3D"providerURL"><string>ldap://127.0.0.1:3=
89,10.0.0.1:389</string></field>
+ <field name=3D"rootdn"><string>CN=3DManager,DC=3Dexopl=
atform,DC=3Dorg</string></field>
+ <field name=3D"password"><string>secret</string>=
</field>
+ <!-- field name=3D"authenticationType"><string>simple=
</string></field--> =
+ <field name=3D"version"><string>3</string></f=
ield>
+ <field name=3D"referralMode"><string>follow</strin=
g></field> =
+ <!-- field name=3D"serverName"><string>active.directo=
ry</string></field-->
+ </object>
+ </object-param>
+ </init-params>
+</component>
+
+
+
+ providerURL: LDAP serve=
r URL
+ (see PROVIDER_URL>http://java.su=
n.com/products/jndi/1.2/javadoc/javax/naming/Context.html#PROVIDER_URL).
+ For multiple ldap servers, use comma separated list of host:port
+ (Ex. ldap://127.0.0.1:389,10.0.0.1:389).
+
+
+
+ rootdn: dn of user that=
will
+ be used by the service to authenticate on the server (see SECURITY_PRINCIPAL=
>http://java.sun.com/products/jndi/1.2/javadoc/javax/naming/Context.html=
#SECURITY_PRINCIPAL).
+
+
+
+ password: password for =
user
+ rootdn (see SECURITY_CREDE=
NTIALS>http://java.sun.com/products/jndi/1.2/javadoc/javax/naming/Contex=
t.html#SECURITY_CREDENTIALS).
+
+
+
+ authenticationType: typ=
e of
+ authentication to be used (see SECURITY=
_AUTHENTICATION>http://java.sun.com/products/jndi/1.2/javadoc/javax/nami=
ng/Context.html#SECURITY_AUTHENTICATION).
+ Use one of none, simple, strong. Default is simple.
+
+
+
+ version: LDAP protocol
+ version (see java.naming.ldap.version>http://ja=
va.sun.com/products/jndi/tutorial/ldap/misc/version.html).
+ Set to 3 if your server supports LDAP V3.
+
+
+
+ referalMode: one of fol=
low,
+ ignore,throw (see REFERRAL>http://java.sun.com/produc=
ts/jndi/1.2/javadoc/javax/naming/Context.html#REFERRAL).
+
+
+
+ serverName: you will ne=
ed to
+ set this to active.directory in order to work with Active Direct=
ory
+ servers. Any other value will be ignore and the service will act=
as
+ on a standard LDAP.
+
+
+
+
+
+ Organization Service Configuration
+
+ Next, you need to configure the eXo OrganizationService to tell him how the dir=
ectory
+ is structured and how to interact with it. This is managed by a coup=
le
+ of of init-params : ldap.userDN.key and
+ ldap.attribute.mapping in file
+ ldap-configuration.xml (by default
+ located at portal.war/WEB-INF/conf/organization)
+
+ <component>
+ <key>org.exoplatform.services.organization.OrganizationService<=
/key>
+ <type>org.exoplatform.services.organization.ldap.OrganizationServi=
ceImpl</type>
+ [...]
+ <init-params>
+ <value-param>
+ <name>ldap.userDN.key</name>
+ <description>The key used to compose user DN</description&g=
t;
+ <value>cn</value>
+ </value-param>
+ <object-param>
+ <name>ldap.attribute.mapping</name>
+ <description>ldap attribute mapping</description>
+ <object type=3D"org.exoplatform.services.organization.ldap.LDAPAt=
tributeMapping">
+ [...]
+ </object-param>
+ </init-params>
+ [...]
+</component>
+
+ ldap.attribute.mapping maps=
your
+ ldap to eXo. At first there are two main parameters to configure in
+ it:
+
+ <field name=3D"baseURL"><string>dc=3Dexo=
platform,dc=3Dorg</string></field>
+<field name=3D"ldapDescriptionAttr"><string>description</st=
ring></field>
+
+
+
+ baseURL: root dn for eXo
+ organizational entities. This entry can't be created by eXo and =
must
+ preexist in directory.
+
+
+
+ ldapDescriptionAttr (si=
nce
+ core 2.2+) : Name of a common attribute that will be used as
+ description for groups and membership types.
+
+
+
+
+ (since core 2.2+) : Name of a common attribute that will be =
used
+ as description for groups and membership types.
+
+
+ Other parameters are discussed in the following sections.
+
+
+ Users
+
+
+ Main parameters
+
+ Here are the main parameters to map eXo users to your
+ directory :
+
+ <field name=3D"userURL"><string>ou=
=3Dusers,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg</string></field>
+<field name=3D"userObjectClassFilter"><string>objectClass=3Dpe=
rson</string></field>
+<field name=3D"userLDAPClasses"><string>top,person,organizatio=
nalPerson,inetOrgPerson</string></field>
+
+
+
+ userURL : base dn f=
or
+ users. Users are created in a flat structure under this base
+ with a dn of the form: ldap.userDN.key=3Dusername,userURL<=
/para>
+
+
+
+ Example :
+
+ uid=3Djohn,cn=3DPeople,o=3DMyCompany,c=3Dcom
+
+ However, if users exist deeply under userURL, eXo will be =
able
+ to retrieve them.
+
+ Example :
+
+ uid=3Dtom,ou=3DFrance,ou=3DEMEA,cn=3DPeople,o=3D=
MyCompany,c=3Dcom
+
+
+
+ userObjectClassFilter:
+ Filter used under userURL branch to distinguish eXo user ent=
ries
+ from others.
+
+
+
+ Example : john and tom will be recognized as valid eXo use=
rs
+ but EMEA and France entries will be ignored in the following sub=
tree
+ :
+
+ uid=3Djohn,cn=3DPeople,o=3DMyCompany,c=3Dcom
+ objectClass: person
+ =E2=80=A6
+ou=3DEMEA,cn=3DPeople,o=3DMyCompany,c=3Dcom
+ objectClass: organizationalUnit
+ =E2=80=A6
+ ou=3DFrance,ou=3DEMEA,cn=3DPeople,o=3DMyCompany,c=3Dcom
+ objectClass: organizationalUnit
+ =E2=80=A6
+ uid=3Dtom,ou=3DEMEA,cn=3DPeople,o=3DMyCompany,c=3Dcom
+ objectClass: person
+ =E2=80=A6
+
+
+
+ userLDAPClasses : c=
omma
+ separated list of classes used for user creation.
+
+
+
+ When creating a new user, an entry will be created with the
+ given objectClass attributes. The classes must at least define cn
+ and any attribute refernced in the user mapping.
+
+ Example : Adding the user Marry Simons could produce :
+
+ uid=3Dmarry,cn=3Dusers,ou=3Dportal,dc=3Dexoplatf=
orm,dc=3Dorg
+ objectclass: top
+ objectClass: person
+ objectClass: organizationalPerson
+ objectClass: inetOrgPerson
+ =E2=80=A6
+
+
+
+ User mapping
+
+ The following parameters maps ldap attributes to eXo User =
java
+ objects attributes.
+
+ <field name=3D"userUsernameAttr"><strin=
g>uid</string></field>
+<field name=3D"userPassword"><string>userPassword</string&g=
t;</field>
+<field name=3D"userFirstNameAttr"><string>givenName</string=
></field>
+<field name=3D"userLastNameAttr"><string>sn</string><=
/field> =
+<field name=3D"userDisplayNameAttr"><string>displayName</st=
ring></field>
+<field name=3D"userMailAttr"><string>mail</string></f=
ield>
+
+
+
+ userUsernameAttr:
+ username (login)
+
+
+
+ userPassword: passw=
ord
+ (used when portal authentication is done by eXo login
+ module)
+
+
+
+ userFirstNameAttr:
+ firstname
+
+
+
+ userLastNameAttr:
+ lastname
+
+
+
+ userDisplayNameAttr:
+ displayed name
+
+
+
+ userMailAttr: email
+ address
+
+
+
+ Example : In the previous example, user Marry Simons could
+ produce :
+
+ uid=3Dmarry,cn=3Dusers,ou=3Dportal,dc=3Dexoplatf=
orm,dc=3Dorg
+ objectclass: top
+ objectClass: person
+ objectClass: organizationalPerson
+ objectClass: inetOrgPerson
+ =E2=80=A6
+
+
+
+
+ Groups
+
+ eXo groups can be mapped to organizational or applicative gr=
oups
+ defined in your directory.
+
+ <field name=3D"groupsURL"><string>ou=
=3Dgroups,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg</string></field>
+<field name=3D"groupLDAPClasses"><string>top,organizationalUni=
t</string></field>
+<field name=3D"groupObjectClassFilter"><string>objectClass=3Do=
rganizationalUnit</string></field>
+
+
+
+ groupsURL : base dn f=
or eXo
+ groups
+
+
+
+ Groups can be structured hierarchically under groupsURL.
+
+ Example: Groups communication, communication/marketing and
+ communication/press would map to :
+
+ ou=3Dcommunication,ou=3Dgroups,ou=3Dportal,dc=3Dex=
oplatform,dc=3Dorg
+=E2=80=A6
+ ou=3Dmarketing,ou=3Dcommunication,ou=3Dgroups,ou=3Dportal,dc=3Dexoplatfo=
rm,dc=3Dorg
+ =E2=80=A6 =
+ ou=3Dpress,ou=3Dcommunication,ou=3Dgroups,ou=3Dportal,dc=3Dexoplatform,d=
c=3Dorg =
+ =E2=80=A6
+
+
+
+ groupLDAPClasses: com=
ma
+ separated list of classes used for group creation.
+
+
+
+ When creating a new group, an entry will be created with the
+ given objectClass attributes. The classes must define at least the
+ required attributes: ou, description and l.
+
+
+ l attribute corresponds to the City property in OU property
+ editor
+
+
+ Example : Adding the group human-resources could produce:
+
+ ou=3Dhuman-resources,ou=3Dgroups,ou=3Dportal,dc=3D=
exoplatform,dc=3Dorg
+ objectclass: top
+ objectClass: organizationalunit
+ ou: human-resources
+ description: The human resources department
+ l: Human Resources
+ =E2=80=A6
+
+
+
+ groupObjectClassFilter:
+ filter used under groupsURL branch to distinguish eXo groups f=
rom
+ other entries. You can also use a complex filter if you
+ need.
+
+
+
+ Example : groups WebDesign, WebDesign/Graphists and Sales co=
uld
+ be retrieved in :
+
+ l=3DParis,dc=3Dsites,dc=3Dmycompany,dc=3Dcom
+ =E2=80=A6
+ ou=3DWebDesign,l=3DParis,dc=3Dsites,dc=3Dmycompany,dc=3Dcom
+ =E2=80=A6
+ ou=3DGraphists,WebDesign,l=3DParis,dc=3Dsites,dc=3Dmycompany,dc=3Dcom
+ =E2=80=A6
+l=3DLondon,dc=3Dsites,dc=3Dmycompany,dc=3Dcom
+ =E2=80=A6
+ ou=3DSales,l=3DLondon,dc=3Dsites,dc=3Dmycompany,dc=3Dcom
+ =E2=80=A6
+
+
+
+ Membership Types
+
+ Membership types are the possible roles that can be assigned=
to
+ users in groups.
+
+ <field name=3D"membershipTypeURL"><string=
>ou=3Dmemberships,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg</string>&l=
t;/field> =
+<field name=3D"membershipTypeLDAPClasses"><string>top,organiza=
tionalRole</string></field>
+<field name=3D"membershipTypeNameAttr"><string>cn</string&g=
t;</field>
+
+
+
+
+
+ membershipTypeURL : b=
ase dn
+ for membership types storage.
+
+
+
+ eXo stores membership types in a flat structure under
+ membershipTypeURL.
+
+ Example : Roles manager, user, admin and editor could by def=
ined
+ by the subtree :
+
+ ou=3Droles,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg
+=E2=80=A6
+ cn=3Dmanager,ou=3Droles,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg
+ =E2=80=A6
+ cn=3Duser,ou=3Droles,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg
+ =E2=80=A6
+ cn=3Dadmin,ou=3Droles,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg =
=
+ =E2=80=A6
+ cn=3Deditor,ou=3Droles,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg
+ =E2=80=A6
+
+
+
+ membershipTypeLDAPClasses:
+ comma separated list of classes for membership types
+ creation.
+
+
+
+ When creating a new membership type, an entry will be created
+ with the given objectClass attributes. The classes must define the
+ required attributes : description,
+ cn
+
+ Example : Adding membership type validator would produce
+ :
+
+ cn=3Dvalidator,ou=3Droles,ou=3Dportal,dc=3Dexoplat=
form,dc=3Dorg
+ objectclass: top
+ objectClass: organizationalRole
+ =E2=80=A6
+
+
+
+ membershipTypeNameAttr :
+ Attribute that will be used as the name of the role
+
+
+
+ Example : If membershipTypeNameAttr is 'cn', then role name =
is
+ 'manager' for the following membership type entry :
+
+ cn=3Dmanager,ou=3Droles,ou=3Dportal,dc=3Dexoplatfo=
rm,dc=3Dorg </pre>
+
+
+
+ Memberships
+
+ Memberships are used to assign a role within a group. They a=
re
+ entries that are placed under the group entry of their scope group.
+ Users in this role are defined as attributes of the membership
+ entry.
+
+ Example: To designate tom as the manager of the group
+ human-resources :
+
+ ou=3Dhuman-resources,ou=3Dgroups,ou=3Dportal,dc=3D=
exoplatform,dc=3Dorg
+ =E2=80=A6
+ cn=3Dmanager,ou=3Dhuman-resources,ou=3Dgroups,ou=3Dportal,dc=3Dexoplatfo=
rm,dc=3Dorg
+ member: uid=3Dtom,ou=3Dusers,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg
+ =E2=80=A6
+
+ The parameters to configure memberships are :
+
+ <field name=3D"membershipLDAPClasses"><st=
ring>top,groupOfNames</string></field>
+<field name=3D"membershipTypeMemberValue"><string>member</s=
tring></field> =
+<field name=3D"membershipTypeRoleNameAttr"><string>cn</stri=
ng></field>
+<field name=3D"membershipTypeObjectClassFilter"><string>object=
Class=3DorganizationalRole</string></field>
+
+
+
+ membershipLDAPClasses=
:
+ comma separated list of classes used to create memberships.
+
+
+
+ When creating a new membership, an entry will be created with
+ the given objectClass attributes. The classes must at least define=
the
+ attribute designated by membershipTypeMemberValue.
+
+ Example : Adding membership validator would produce :
+
+ cn=3Dvalidator,ou=3Dhuman-resources,ou=3Dgroups,ou=
=3Dportal,dc=3Dexoplatform,dc=3Dorg
+ objectclass: top
+ objectClass: groupOfNames
+ =E2=80=A6
+
+ <pre>
+ cn=3Dvalidator,ou=3Dhuman-resources,ou=3Dgroups,ou=3Dportal,dc=3De=
xoplatform,dc=3Dorg
+ objectclass: top objectClass: groupOfNames ... </pre>
+
+
+
+ membershipTypeMemberValue:
+ Multivalued attribute used in memberships to reference users t=
hat
+ have the role in the group.
+
+
+
+ Values should be a user dn.
+
+ Example: james and root have admin role within the group
+ human-resources, would give:
+
+ cn=3Dadmin,ou=3Dhuman-resources,ou=3Dgroups,ou=3Dp=
ortal,dc=3Dexoplatform,dc=3Dorg
+ member: cn=3Djames,ou=3Dusers,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg
+ member: cn=3Droot,ou=3Dusers,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg
+ =E2=80=A6
+
+
+
+ membershipTypeRoleNameAttr:
+ Attribute of the membership entry whose value references the
+ membership type.
+
+
+
+ Example : In the following membership entry:
+
+ <pre>
+ cn=3Dmanager,ou=3Dhuman-resources,ou=3Dgroups,ou=3Dportal,dc=3Dexo=
platform,dc=3Dorg
+ </pre>
+
+ 'cn' attribute is used to designate the 'manager' membership
+ type. Which could also be said : The name of the role is given by =
'cn'
+ the attribute.
+
+
+
+ membershipTypeObjectClassFilter : Fil=
ter
+ used to distinguish membership entries under groups.
+
+
+
+ You can use rather complex filters.
+
+ Example: Here is a filter we used for a customer that needed=
to
+ trigger a dynlist overlay on openldap.
+
+ (&(objectClass=3DExoMembership)(membership=
URL=3D*)) =
+
+
+ Note : Pay attention to the xml escaping of the '&' (and)
+ operator
+
+
+
+ User Profiles
+
+ eXo User profiles also have entries in the ldap but the actu=
al
+ storage is still done with the hibernate service. You will need the
+ following parameters :
+
+ <field name=3D"profileURL"><string>ou=
=3Dprofiles,ou=3Dportal,dc=3Dexoplatform,dc=3Dorg</string></field&=
gt;
+<field name=3D"profileLDAPClasses"><string>top,organizationalP=
erson</string></field>
+
+
+
+ profileURL: base dn to
+ store user profiles
+
+
+
+ profileLDAPClasses: C=
lasses
+ used to when creating user profiles
+
+
+
+
+
+
+
+ Advanced topics
+
+
+ Automatic directory population
+
+ At startup eXo can populate the organization model based on
+
+ eXo organizational model has User,Group,Membership and Profile
+ entities. For each, we define a base dn that should be below baseURL=
. At
+ startup, if one of userURL, groupsURL, membershipTypeURL or profileU=
RL
+ does not exist fully, eXo will attempt to create the missing subtree=
by
+ parsing the dn and creating entries on-the-fly. To determine the cla=
sses
+ of the created entries, the following rules are applied :
+
+
+
+ ou=3D... : objectClass=3Dtop,objectClass=3DorganizationalU=
nit
+
+
+
+ cn=3D... : objectClass=3Dtop,objectClass=3DorganizationalR=
ole
+
+
+
+ c=3D... : objectClass=3Dcountry
+
+
+
+ o=3D... : objectClass=3Dorganization
+
+
+
+ dc=3D.. :
+ objectClass=3Dtop,objectClass=3DdcObject,objectClass=3Dorganizat=
ion
+
+
+
+ Example:
+
+ If baseURL is o=3DMyCompany,c=3Dcom
+ and groupsURL is dc=3Dgroups,cn=3DExtranet,c=3DFrance,ou=3DEMEA,o=3DMyC=
ompany,c=3Dcom
+ then, the following subtree will be created :
+
+ ou=3DEMEA,o=3DMyCompany,c=3Dcom
+ objectClass: top
+ objectClass: organizationalUnit
+ =E2=80=A6
+ c=3DFrance,ou=3DEMEA,o=3DMyCompany,c=3Dcom
+ objectClass: top
+ objectClass: country
+ =E2=80=A6
+ cn=3DExtranet,c=3DFrance,ou=3DEMEA,o=3DMyCompany,c=3Dcom
+ objectClass: top
+ objectClass: organizationalRole
+ =E2=80=A6
+ dc=3Dgroups,cn=3DExtranet,c=3DFrance,ou=3DEMEA,o=3DMyCompany,c=3Dc=
om
+ objectClass: top
+ objectClass: dcObject
+ objectClass: organization =
+ =E2=80=A6
+
+
+
+ Active Directory sample configuration
+
+ Here is an alternative configuration for active directory that=
you
+ can find in activedirectory-configuration.xml
+
+
+ There is a microsoft limitation: password can't be set in AD=
via
+ unsecured connection you have to use the ldaps protocol
+
+
+ #info("There is a microsoft limitation: password can't be set =
in
+ AD via unsecured connection you have to use the ldaps protocol")
+
+ here is how to use LDAPS protocol with Active Directory :
+
+ 1 setup AD to use SSL:
+
+ * add Active Directory Certificate Services role
+ * install right certificate for DC machine
+
+2 enable Java VM to use certificate from AD:
+
+ * import root CA used in AD, to keystore, something like
+
+ keytool -importcert -file 2008.cer -keypass changeit -keystore /home=
/user/java/jdk1.6/jre/lib/security/cacerts
+
+ * set java options
+
+ JAVA_OPTS=3D"${JAVA_OPTS} -Djavax.net.ssl.trustStorePassword=3Dchang=
eit -Djavax.net.ssl.trustStore=3D/home/user/java/jdk1.6/jre/lib/security/ca=
certs"
+
+ [...]
+ <component>
+ <key>org.exoplatform.services.ldap.LDAPService</key>
+[..]
+ <object type=3D"org.exoplatform.services.ldap.impl.LDAPConnecti=
onConfig"> =
+ <!-- for multiple ldap servers, use comma seperated list of ho=
st:port (Ex. ldap://127.0.0.1:389,10.0.0.1:389) -->
+ <!-- whether or not to enable ssl, if ssl is used ensure that the j=
avax.net.ssl.keyStore & java.net.ssl.keyStorePassword properties are se=
t -->
+ <!-- exo portal default installed javax.net.ssl.trustStore with fil=
e is java.home/lib/security/cacerts-->
+ <!-- ldap service will check protocol, if protocol is ldaps, ssl is=
enable (Ex. for enable ssl: ldaps://10.0.0.3:636 ;for disable ssl: ldap://=
10.0.0.3:389 ) -->
+ <!-- when enable ssl, ensure server name is *.directory and port (E=
x. active.directory) --> =
+ <field name=3D"providerURL"><string>ldaps://10.0.0.3:636&=
lt;/string></field>
+ <field name=3D"rootdn"><string>CN=3DAdministrator,CN=3DUs=
ers, DC=3Dexoplatform,DC=3Dorg</string></field>
+ <field name=3D"password"><string>site</string></=
field> =
+ <field name=3D"version"><string>3</string></fiel=
d> =
+ <field name=3D"referralMode"><string>ignore</string=
></field> =
+ <field name=3D"serverName"><string>active.directory<=
;/string></field> =
+ </object>
+[..]
+ <component>
+ <key>org.exoplatform.services.organization.OrganizationService&l=
t;/key>
+ [...]
+ <object type=3D"org.exoplatform.services.organization.ldap.LDAP=
AttributeMapping"> =
+ [...]
+ <field name=3D"userAuthenticationAttr"><string>mail=
</string></field>
+ <field name=3D"userUsernameAttr"><string>sAMAccount=
Name</string></field>
+ <field name=3D"userPassword"><string>unicodePwd<=
/string></field> =
+ <field name=3D"userLastNameAttr"><string>sn</str=
ing></field>
+ <field name=3D"userDisplayNameAttr"><string>display=
Name</string></field>
+ <field name=3D"userMailAttr"><string>mail</strin=
g></field>
+ [..]
+ <field name=3D"membershipTypeLDAPClasses"><string>t=
op,group</string></field>
+ <field name=3D"membershipTypeObjectClassFilter"><strin=
g>objectClass=3Dgroup</string></field>
+ [..]
+ <field name=3D"membershipLDAPClasses"><string>top,g=
roup</string></field>
+ <field name=3D"membershipObjectClassFilter"><string>=
;objectClass=3Dgroup</string></field>
+ </object>
+ [...] =
+</component>
+
+
+
+ OpenLDAP dynlist overlays
+
+ If you use OpenLDAP, you may want to use the overlays
+ > http://www.openldap.org/faq/data/cache/1169.html. Here =
is
+ how you can use the dynlist
+ overlay > http://www.openldap.org/faq/data/cache/1209.html to
+ have memberships dynamically populated.
+
+ The main idea is to have your memberships populated dynamicall=
y by
+ an ldap query. Thus, you no longer have to maintain manually the rol=
es
+ on users.
+
+ To configure the dynlist, add the following to your slapd.conf :
+
+ dynlist-attrset ExoMembership membershipURL =
member
+
+ This snipet means : On entries that have ExoMembership class, =
use
+ the URL defined in the value of attribute membershipURL as a query a=
nd
+ populate results under the multivalues attribute member.
+
+ Now let's declare the corresponding schema (replace XXXXX to a=
dapt
+ to your own IANA code):
+
+ attributeType ( 1.3.6.1.4.1.XXXXX.1.59 NAME 'members=
hipURL' SUP memberURL )
+
+ membershipURL inherits from memberURL.
+
+ objectClass ( 1.3.6.1.4.1.XXXXX.2.12 NAME 'ExoMembe=
rship' SUP top MUST ( cn ) MAY (membershipURL $ member $ description ) )
+
+ ExoMembership must define cn and can have attributes :
+
+
+
+ membershipURL: trigger for the dynlist
+
+
+
+ member : attribute populated by the dynlist
+
+
+
+ description : used by eXo for display
+
+
+
+ # the TestGroup group
+dn: ou=3Dtestgroup,ou=3Dgroups,ou=3Dportal,o=3DMyCompany,c=3Dcom
+objectClass: top
+objectClass: organizationalUnit
+ou: testgroup
+l: TestGroup
+description: the Test Group
+
+ On this group, we can bind an eXo membership where the overlay
+ will occur:
+
+ # the manager membership on group TestGroup
+dn: cn=3Dmanager, ou=3DTestGroup,ou=3Dgroups,ou=3Dportal,o=3DMyCompany,c=
=3Dcom
+objectClass: top
+objectClass: ExoMembership
+membershipURL: ldap:///ou=3Dusers,ou=3Dportal,o=3DMyCompany,c=3Dcom??sub?(=
uid=3D*)
+cn: manager
+
+ This dynlist assigns the role manager:/testgroup to any user.
+
+
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/organization-service-initalizer.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/organization-service-initalizer.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/organization-service-initalizer.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,180 @@
+
+
+
+ Organization Service Initializer
+
+ Use the Organization Service Initializer to create users, groups a=
nd
+ membership types by default.
+
+ <external-component-plugins>
+ <target-component>org.exoplatform.services.organization.Organiza=
tionService</target-component>
+ <component-plugin>
+ <name>init.service.listener</name>
+ <set-method>addListenerPlugin</set-method>
+ <type>org.exoplatform.services.organization.OrganizationDataba=
seInitializer</type>
+ <description>this listener populate organization data for the =
first launch</description>
+ <init-params>
+ <value-param>
+ <name>checkDatabaseAlgorithm</name>
+ <description>check database</description>
+ <value>entry</value>
+ </value-param>
+ <value-param>
+ <name>printInformation</name>
+ <description>Print information init database</descripti=
on>
+ <value>false</value>
+ </value-param>
+ <object-param>
+ <name>configuration</name>
+ <description>description</description>
+ <object type=3D"org.exoplatform.services.organization.Organiz=
ationConfig">
+ <field name=3D"membershipType">
+ <collection type=3D"java.util.ArrayList">
+ <value>
+ <object type=3D"org.exoplatform.services.organization=
.OrganizationConfig$MembershipType">
+ <field name=3D"type">
+ <string>manager</string>
+ </field>
+ <field name=3D"description">
+ <string>manager membership type</string>
+ </field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ =
+ <field name=3D"group">
+ <collection type=3D"java.util.ArrayList">
+ <value>
+ <object type=3D"org.exoplatform.services.organization=
.OrganizationConfig$Group">
+ <field name=3D"name">
+ <string>platform</string>
+ </field>
+ <field name=3D"parentId">
+ <string></string>
+ </field>
+ <field name=3D"description">
+ <string>the /platform group</string>
+ </field>
+ <field name=3D"label">
+ <string>Platform</string>
+ </field>
+ </object>
+ </value>
+ <value>
+ <object type=3D"org.exoplatform.services.organization=
.OrganizationConfig$Group">
+ <field name=3D"name">
+ <string>administrators</string>
+ </field>
+ <field name=3D"parentId">
+ <string>/platform</string>
+ </field>
+ <field name=3D"description">
+ <string>the /platform/administrators group<=
/string>
+ </field>
+ <field name=3D"label">
+ <string>Administrators</string>
+ </field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ =
+ <field name=3D"user">
+ <collection type=3D"java.util.ArrayList">
+ <value>
+ <object type=3D"org.exoplatform.services.organization=
.OrganizationConfig$User">
+ <field name=3D"userName">
+ <string>root</string>
+ </field>
+ <field name=3D"password">
+ <string>exo</string>
+ </field>
+ <field name=3D"firstName">
+ <string>Root</string>
+ </field>
+ <field name=3D"lastName">
+ <string>Root</string>
+ </field>
+ <field name=3D"email">
+ <string>root(a)localhost</string>
+ </field>
+ <field name=3D"groups">
+ <string>
+ manager:/platform/administrators
+ </string>
+ </field>
+ </object>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+
+ Params for membership type:
+
+
+
+ type - The membership type's name
+
+
+
+ description - The membership type's description
+
+
+
+ Params for group:
+
+
+
+ name - The group's name
+
+
+
+ parentId - The id of the parent group. If the parent id is nul=
l,
+ it mean that the group is at the first level. The parentId should ha=
ve
+ the form: /ancestor/parent
+
+
+
+ description - The group's description
+
+
+
+ label - The group's label
+
+
+
+ Params for user:
+
+
+
+ userName - The user's name
+
+
+
+ password - The user's password
+
+
+
+ firstName - The user's first name
+
+
+
+ lastName - The user's last name
+
+
+
+ email - The user's email
+
+
+
+ groups - The user's membership types and groups in which he
+ consist.
+
+
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/organization-service-listener.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/organization-service-listener.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/organization-service-listener.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,181 @@
+
+
+
+ Organization Listener
+
+
+ Overview
+
+ The Organization
+ ServiceThe Core Organization Service provides a mechanism to
+ receive notifications when :
+
+
+
+ a User is created, deleted or modified
+
+
+
+ a Group is created, deleted or modified
+
+
+
+ a Membership is created or removed
+
+
+
+ This mechanism is very useful to cascade some actions when the
+ organization model is modified. For example, it is currently used to
+ :
+
+
+
+ initialize the personal portal pages
+
+
+
+ initialize the personal calendars, address books and mail
+ accounts in CS
+
+
+
+ create drives and personal areas in ECM
+
+
+
+
+
+ Writing your own listeners
+
+ To implement your own listener you just need to write extend some
+ existing listener classes. These classes define hooks that are invoked
+ before or after operations are performed on organization model.
+
+
+ UserEventListener
+
+ To listen to user changes, you need to extend
+ <>org.exoplatform.services.organization.UserEventListener</=
>
+ :
+
+ public class MyUserListener extends UserEventListene=
r {
+
+ public void preSave(User user, boolean isNew) throws Exception {
+ System.out.println("Before " + (isNew?"creating":"updating") + " user =
" + user.getUserName());
+ }
+
+ public void postSave(User user, boolean isNew) throws Exception { =
+ System.out.println("After user " + user.getUserName() + (isNew?" creat=
ed":" updated"));
+ }
+
+ public void preDelete(User user) throws Exception {
+ System.out.println("Before deleting user " + user.getUserName());
+ }
+
+ public void preDelete(User user) throws Exception {
+ System.out.println("After deleting user " + user.getUserName());
+ }
+
+}
+
+
+
+ GroupEventListener
+
+ To listen to group changes, you need to extend
+ <>org.exoplatform.services.organization.GroupEventListener<=
/>
+ :
+
+ public class MyGroupListener extends GroupEventListe=
ner {
+
+ public void preSave(Group group, boolean isNew) throws Exception {
+ System.out.println("Before " + (isNew?"creating":"updating") + " group=
" + group.getName());
+ }
+
+ public void postSave(Group group, boolean isNew) throws Exception { =
+ System.out.println("After group " + group.getName() + (isNew?" created=
":" updated"));
+ }
+
+ public void preDelete(Group group) throws Exception {
+ System.out.println("Before deleting group " + group.getName());
+ }
+
+ public void preDelete(Group group) throws Exception {
+ System.out.println("After deleting group " + group.getName());
+ }
+}
+
+
+
+ MembershipEventListener
+
+ To listen to membership changes, you need to extend
+ <>org.exoplatform.services.organization.MembershipEventListene=
r</>
+ :
+
+ public class MyMembershipListener extends Membership=
EventListener {
+
+ public void preSave(Membership membership, boolean isNew) throws Excepti=
on {
+ System.out.println("Before " + (isNew?"creating":"updating") + " membe=
rship.");
+ }
+
+ public void postSave(Membership membership, boolean isNew) throws Except=
ion { =
+ System.out.println("After membership " + (isNew?" created":" updated")=
);
+ }
+
+ public void preDelete(Membership membership) throws Exception {
+ System.out.println("Before deleting membership");
+ }
+
+ public void preDelete(Membership membership) throws Exception {
+ System.out.println("After deleting membership");
+ }
+}
+
+
+
+
+ Registering your listeners
+
+ Registering the listeners is then achieved by using the ExoConta=
iner
+ plugin mechanism. Learn more about it on the Service Configurati=
on for
+ Beginners article.
+
+ To effectively register organization service's listeners you sim=
ply
+ need to use the <>addListenerPlugin</> seer injector.
+
+ So, the easiest way to register your listeners is to pack them i=
nto
+ a .jar and create a configuration file into it under mylisteners.jar!/conf/portal/configuration.xml
+
+ <?xml version=3D"1.0" encoding=3D"ISO-8859-1"?>
+<configuration>
+ <external-component-plugins>
+ <target-component>org.exoplatform.services.organization.Organizati=
onService</target-component>
+ <component-plugin>
+ <name>myuserplugin</name>
+ <set-method>addListenerPlugin</set-method>
+ <type>org.example.MyUserListener</type>
+ <description></description> =
+ </component-plugin>
+ <component-plugin>
+ <name>mygroupplugin</name>
+ <set-method>addListenerPlugin</set-method>
+ <type>org.example.MyGroupListener</type>
+ <description></description> =
+ </component-plugin>
+ <component-plugin>
+ <name>mymembershipplugin</name>
+ <set-method>addListenerPlugin</set-method>
+ <type>org.example.MyMembershipListener</type>
+ <description></description> =
+ </component-plugin>
+ </external-component-plugins>
+<configuration>
+
+ Now, simply deploy the jar under $TOMCAT_HOME/lib and your liste=
ners
+ are ready!
+
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/organization-service.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/organization-service.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/organization-service.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,148 @@
+
+
+
+ Organization Service
+
+
+ Overview
+
+ OrganizationService is the service that allows to access the
+ Organization model. This model is composed of :
+
+
+
+ Users
+
+
+
+ Groups
+
+
+
+ Memberships
+
+
+
+ It is the basis of eXo personalization and authorizations in eXo=
and
+ is used allover the platform. The model is abstract and does not rely =
on
+ any specific storage. Multiple implementations exist in exo :
+
+
+
+ hibernate : for storage into a RDBMS
+
+
+
+ jndi : for storage into a directory such as an LDAP or MS Ac=
tive
+ Directory
+
+
+
+ jcr : for storage inside a Java Content Repository
+
+
+
+
+
+ Organizational Model
+
+
+ User
+
+
+
+ username used as the identified
+
+
+
+ Profile (identity and preferences)
+
+
+
+
+
+ Group
+
+ Gather a set of users
+
+
+
+ applicative or business
+
+
+
+ tree structure
+
+
+
+ no inheritance
+
+
+
+ expressed as /group/subgroup/subsubgroup
+
+
+
+
+
+ Membership
+
+
+
+ qualifies the group belonging
+
+
+
+ "Member of group as XXX"
+
+
+
+ expressed as : manager:/organization/hr, *:/partners
+
+
+
+
+
+
+ Related articles and how-tos
+
+
+
+ JCR
+ Organization Service
+
+
+
+
+
+ Update
+ ConversationState when user's Membership changed
+
+
+
+ Organization
+ Service Initializer
+
+
+
+ How
+ to Access User Profile in your code
+
+
+
+ How to create your o=
wn
+ Organization Listener
+
+
+
+ H=
ow to
+ manipulate Users and Memberships Programmatically
+
+
+
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/security-service.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/security-service.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/security-service.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,309 @@
+
+
+
+ Security Service
+
+
+ 1 Overview
+
+ The purpose is to make a simple, unified way for the authenticat=
ion
+ and the storing/propagation of user sessions through all the eXo
+ components and J2EE containers. JAAS is supposed to be the primary log=
in
+ mechanism but the Security Service framework should not prevent other
+ (custom or standard) mechanisms from being used. You can learn more ab=
out
+ JAAS in the Java
+ Tutorial>http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/tu=
torials/GeneralAcnAndAzn.html
+
+
+
+ 1 Framework
+
+ The central point of this framework is the ConversationState object which stores all
+ information about the state of the current user (very similar to the
+ Session concept). The same ConversationState also stores acquired
+ attributes of an Identity which is =
a set
+ of principals to identify a user.
+
+ The ConversationState has definite lifetime. This object should =
be
+ created when the user's identity becomes known by eXo (login procedure)
+ and destroyed when the user leaves an eXo based application (logout
+ procedure). Using JAAS it should happen in LoginModule's login() and
+ logout() methods respectively.
+
+
+ 1.1 ConversationState and ConversationRegistry
+
+ The ConversationState can be stored
+
+
+
+ in a static local thread
+ variable, or
+
+
+
+ as a key-value pair in =
the
+ ConversationRegistry
+ component.
+
+
+
+ One or the other, or both methods can be used to set/retrieve =
the
+ state at runtime. The most important thing is that they should be
+ complementary, i.e. make sure that the conversation state is set bef=
ore
+ you try to use it.
+
+ Local Thread Variable Stori=
ng the
+ ConversationState in a static local thread variable makes it possibl=
e to
+ represent it as a context (current
+ user's state).
+
+ ConversationState.setCurrent(conversationState);
+....
+ConversationState.getCurrent();
+
+ Key-Value way
+
+ If you store the ConversationState inside the ConversationRegistry component as a set of
+ key-value pairs, the session key is an arbitrary String (user name,
+ ticket id, httpSessionId etc).
+
+ conversationRegistry.register("key", conversationSta=
te); =
+...
+conversationRegistry.getState("key");
+
+ ConversationRegistry The
+ ConversationRegistry is a mandatory component deployed into eXo
+ Container as following:
+
+ <component>
+ <type>org.exoplatform.services.security.ConversationRegistry<=
/type>
+</component>
+
+
+
+ 1.1 Authenticator
+
+ An Authenticator is responsible for Identity creating, it cont=
ains
+ two methods:
+
+
+
+ validateUser() accepts an array of credentials and returns=
the
+ userId (which can be something different from the username).
+
+
+
+ createIdentity() accepts the userId and returns a newly
+ created Identity object.
+
+
+
+ public interface Authenticator {
+ /**
+ * Authenticate user and return userId which can be different to usernam=
e. =
+ * @param credentials - list of users credentials (such as name/password=
, X509 certificate etc)
+ * @return userId
+ * @throws LoginException
+ * @throws Exception
+ */
+ String validateUser(Credential[] credentials) throws LoginException, Exc=
eption;
+
+ /**
+ * @param credentials - userId.
+ * @return Identity
+ * @throws Exception
+ */
+ Identity createIdentity(String userId) throws Exception; =
+
+}
+
+ It is up to the application developer (and deployer) whether to
+ use the Authenticator component(s) and how many implementations of t=
his
+ components should be deployed in eXo container. The developer is fre=
e to
+ create an Identity object using a different way, but the Authenticat=
or
+ component is the highly recommended way from architectural
+ considerations.
+
+ Typical functionality of the validateUser(Credential\[]
+ credentials) method is the comparison of incoming credentials
+ (username/password, digest etc) with those credentials that are stor=
ed
+ in an implementation specific database. Then validateUser(Credential=
\[]
+ credentials) returns back the userId or throws a LoginException in a
+ case of wrong credentials.
+
+ Default Authenticator implementation is
+ org.exoplatform.services.organization.auth.OrganizationAuthenticator=
Impl
+ which compares incoming username/password credentials with the ones
+ stored in OrganizationService. Configuration example:
+
+ <component>
+ <key>org.exoplatform.services.security.Authenticator</key> =
+ <type>org.exoplatform.services.organization.auth.OrganizationAuthe=
nticatorImpl</type>
+</component>
+
+
+
+
+ Usage
+
+
+ JAAS login module
+
+ The framework described is not coupled with any authentication
+ mechanism but the most logical and implemented by default is the JAAS
+ Login module. The typical sequence looks as follows (see
+ org.exoplatform.services.security.jaas.DefaultLoginModule):
+
+
+
+ LoginModule.login() creates a list of credentials using
+ standard JAAS Callbacks features, obtains an Authenticator insta=
nce,
+ and creates an Identity object calling
+ Authenticator.authenticate(..) method
+
+
+
+ Authenticator authenticator =3D (Authenticator) cont=
ainer()
+ .getComponentInstanceOfType(Authenticator.class); =
+// RolesExtractor can be null =
+RolesExtractor rolesExtractor =3D (RolesExtractor) container().
+getComponentInstanceOfType(RolesExtractor.class);
+
+
+Credential[] credentials =3D new Credential[] {new UsernameCredential(user=
name), new PasswordCredential(password) };
+String userId =3D authenticator.validateUser(credentials);
+identity =3D authenticator.createIdentity(userId);
+
+
+
+ LoginModule.commit() obtains the IdentityRegistry object, =
and
+ register the identity using userId as a key.
+
+
+
+ When initializing the login module you can set the option
+ parameter "singleLogin". With this option you can disallow the same
+ Identity to login for a second time.
+
+ By default singleLogin is disabled, so the same identity can be
+ registered more than one time. Parameter can be passed in this form
+ singleLogin=3Dyes or singleLogin=3Dtrue.
+
+ IdentityRegistry identityRegistry =3D (IdentityRegis=
try) getContainer().getComponentInstanceOfType(IdentityRegistry.class);
+ =
+if (singleLogin && identityRegistry.getIdentity(identity.getUserId=
()) !=3D null) =
+ throw new LoginException("User " + identity.getUserId() + " already logi=
ned.");
+
+identity.setSubject(subject);
+identityRegistry.register(identity);
+
+ In the case of using several LoginModules, JAAS allows to place
+ the login() and commit() methods in different REQUIRED modules.
+
+ After that, the web application must use SetCurrentIdentityFil=
ter.
+ This filter obtains the ConversationRegistry object and tries to get=
the
+ ConversationState by sessionId (HttpSession). If there is no
+ ConversationState then SetCurrentIdentityFilter will create a new on=
e,
+ register it and set it as current one using
+ ConversationState.setCurrent(state).
+
+
+
+ LoginModule.logout() can be called by
+ JAASConversationStateListener, it extends
+ ConversationStateListener.
+
+
+
+ This listener must be configured in web.xml. The method
+ sessionDestroyed(HttpSessionEvent)is called by the ServletContainer.
+ This method removes the ConversationState from the ConversationRegis=
try
+ ConversationRegistry.unregister(sesionId) and calls the method
+ LoginModule.logout().
+
+ ConversationRegistry conversationRegistry =3D (Conve=
rsationRegistry) getContainer().getComponentInstanceOfType(ConversationRegi=
stry.class);
+
+ConversationState conversationState =3D conversationRegistry.unregister(se=
sionId);
+
+if (conversationState !=3D null) {
+ log.info("Remove conversation state " + sesionId);
+ if (conversationState.getAttribute(ConversationState.SUBJECT) !=3D null)=
{
+ Subject subject =3D (Subject) conversationState.getAttribute(Conversat=
ionState.SUBJECT); =
+ LoginContext ctx =3D new LoginContext("exo-domain", subject);
+ ctx.logout();
+} else {
+ log.warn("Subject was not found in ConversationState attributes.");
+}
+
+
+
+
+
+ 1.1 Predefinded JAAS login modules
+
+ There are several JAAS Login modules included in eXo Platform
+ sources:
+
+ org.exoplatform.services.security.jaas.DefaultLoginMod=
ule
+ which provides both authentication (using eXo Authenticator based
+ mechanism) and authorization, filling Conversation Registry as it
+ described in previous section. There are also several per-Application
+ Server extensions of this login module which can be found in
+ org.exoplatform.services.security.jaas package, which can be used in
+ appropriate AS. In particular, we have dedicated Login modules for
+ Tomcat, JBoss, Jonas and WebSphere.
+
+ TODO: configuration examples for Tomca=
t,
+ JBoss, Jonas and WebSphere
+
+ Besides that, for the case when third party authentication
+ mechanism required, we have org.exoplatform.services.security.jaas.IdentitySetLogi=
nModule,
+ which catches a login identity from third party "authenticating" log=
in
+ module and preforms eXo specific authorization job. In this case thi=
rd
+ party login module has to put login (user) name to the shared state =
map
+ under "javax.security.auth.login.name"
+ key and third party LM has to be configured before
+ IdentitySetLoginModule like:
+
+ exo {
+ com.third.party.LoginModuleImpl required;
+ org.exoplatform.services.security.jaas.IdentitySetLoginModule required;
+};
+
+
+
+ 1.1 J2EE container authentication
+
+ As you know, when a user in JAAS is authenticated, a Subject is
+ created as a result. This Subject represents the authenticated user.=
It
+ is important to know and follow the rules regarding Subject filling
+ which are specific for each J2EE server, where eXo Platform is
+ deployed.
+
+ To make it workable for the particular J2EE server it is neces=
sary
+ to add specific Principals/Credentials to the Subject to be propagat=
ed
+ into the specific J2EE container implementation. We extended the
+ DefaultLoginModule by overloading its commit() method with a dedicat=
ed
+ logic, presently available for Tomcat, JBOSS and JONAS application
+ servers.
+
+ Furthermore you can use the optional RolesExtractor which is
+ responsible for mapping primary Subject's principals (userId and a s=
et
+ of groups) to J2EE Roles:
+
+ public interface RolesExtractor {
+ Set <String> extractRoles(String userId, Set<MembershipEntry>=
; memberships);
+}
+
+ This component may be used by Authenticator to create the Iden=
tity
+ with a particular set of Roles.=
para>
+
+
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules=
/core/spring-security-integration.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/spring-security-integration.xml (rev 0)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re/spring-security-integration.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -0,0 +1,670 @@
+
+
+
+ Spring Security Integration
+
+
+ Introduction
+
+ How to Integrate the spring security framework in the eXo
+ portal?
+
+ This tutorial will guide you through a few steps and show you how
+ easy it is to integrate spring security (or the Spring framework in
+ general) in eXo portal. We will create a login portlet example as a
+ support all along the document reading. The login portlet example has =
been
+ developed and deployed using the eXo WCM product running on the
+ application server JBoss 4.2.3. But it can easily be adapted to another
+ eXo product (such as ECM) and to other servers such as tomcat. Moreove=
r,
+ the example, claiming to be a real world example, is implemented using=
JSF
+ 1.2, the JBoss portlet bridge and Spring and can serve as a example
+ project from where you can start your own portlet development targeting
+ the eXo platform.
+
+
+
+ Installation
+
+ This tutorial assumes that you have a working eXo WCM installati=
on
+ running under JBoss 4.2.x.
+
+ Download the spring framework: http://s3.amazonaws.com/dist.sp=
ringframework.org/release/SPR/spring-framework-2.5.6-with-dependencies.zip<=
/ulink>
+
+ Download spring-security: http://sourceforge.net/proj=
ect/showfiles.php?group_id=3D73357&package_id=3D270072&release_id=
=3D630203
+
+ Unzip the 02portal.war file in the jboss
+ server/default/deploy/exoplatform.sar directory and copy the following
+ jars in WEB-INF/lib:
+
+
+
+ spring.jar
+
+
+
+ spring-security-core.jar
+
+
+
+ aspectjrt-1.5.4.jar
+
+
+
+ exo-spring.jar (contains the filters and event handlers
+ described in this tutorial - see the attachment section of this
+ page)
+
+
+
+
+
+ Configuration
+
+ To enable spring security in exo we need to go through a few
+ configuration steps:
+
+
+ JAAS disabling
+
+ First we need to disable the JAAS security which is the default
+ authentication mechanism in exo. Edit 02portal.war web.xml file and
+ comment out the JAAS configuration related lines:
+
+ ...
+ <session-config>
+ <session-timeout>15</session-timeout>
+ </session-config>
+
+ <!--
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>user authentication</web-resource-nam=
e>
+ <url-pattern>/private/*</url-pattern>
+ <http-method>POST</http-method>
+ <http-method>GET</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>users</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>NONE</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+ =
+ <login-config>
+ <auth-method>FORM</auth-method>
+ <realm-name>exo-domain</realm-name>
+ <form-login-config>
+ <form-login-page>/login/jsp/login.jsp</form-login-page&g=
t;
+ <form-error-page>/login/jsp/login.jsp</form-error-page&g=
t;
+ </form-login-config>
+ </login-config>
+ -->
+
+ <security-role>
+ <description>a simple user role</description>
+ <role-name>users</role-name>
+ </security-role>
+...
+
+
+
+ Enabling spring security
+
+ To enable spring and set the spring security filter, add the
+ following lines:
+
+ ...
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>/WEB-INF/security-context.xml</param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderL=
istener</listener-class>
+ </listener>
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterP=
roxy</filter-class>
+ </filter>
+...
+
+ Activate the spring security filter at the right position, i.e.
+ just after the filter responsible of exo container
+ initialization.
+
+ ...
+ <filter-mapping>
+ <filter-name>PortalContainerInitializedFilter</filter-name&=
gt;
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>SetCurrentIdentityFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+...
+
+
+
+ security-context.xml
+
+ We need to configure the spring security filter chain for our
+ purposes. Create a file named security-context.xml in 02portal.war
+ WEB-INF directory containing the following lines:
+
+ <?xml version=3D"1.0" encoding=3D"UTF-8"?>
+<beans:beans xmlns=3D"http://www.springframework.org/schema/security"
+ xmlns:beans=3D"http://www.springframework.org/schema/beans"
+ xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation=3D"http://www.springframework.org/schema/beans http:=
//www.springframework.org/schema/beans/spring-beans-2.0.xsd
+ http://www.springframework.org/schema/security http=
://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
+
+ <http auto-config=3D"true">
+ <intercept-url pattern=3D"/private/**" access=3D"ROLE_USER" />=
=
+ <form-login login-page=3D'/public/classic/Login' default-target-u=
rl=3D'/private/classic/home' />
+ </http>
+ =
+ <authentication-provider>
+ <user-service>
+ <user name=3D"rod" password=3D"koala" authorities=3D"ROLE_SUPE=
RVISOR, ROLE_USER, ROLE_TELLER" />
+ <user name=3D"root" password=3D"exo" authorities=3D"ROLE_USER"=
/>
+ </user-service>
+ </authentication-provider> =
+
+</beans:beans>
+
+ The file contains two elements. The http node which is respons=
ible
+ of configuring the filter chain. The auto-config mode set to true al=
lows
+ us to do just a minimal configuration, everything else being smartly
+ initialized by default. We just set an intercept URL pointing to
+ '/private/**' with the ROLE_USER authority which corresponds to secu=
red
+ resources in exo. In case of successful auhentication, the user will=
be
+ redirected to the specified default target URL.
+
+ The second element defines a simple authentication provider ba=
sed
+ on the spring security InMemoryDaoImpl implementation of the
+ UserDetailsService. Note that we define the exo root user in the
+ configuration which will allow us to log in with admin privileges in=
the
+ exo portal.
+
+
+
+
+ Login portlet example
+
+ Now that we have successfully installed and configured spring
+ security in exo, we need a login portlet example to capture user
+ credentials and serve as an entry point in the authentication process.=
The
+ login portlet itself is based on JSF 1.2, Jboss portlet bridge and the
+ spring framework, but you can obviously use whatever web framework you
+ want to achieve the same.
+
+
+ Building the portlet
+
+ So we need a login form to capture user credentials inputs. The
+ portlet login form consists of the following lines of xml:
+
+ <f:view xmlns:f=3D"http://java.sun.com/jsf/core"
+ xmlns:h=3D"http://java.sun.com/jsf/html"
+ xmlns:ice=3D"http://www.icesoft.com/icefaces/component"
+ xmlns:liferay-faces=3D"http://liferay.com/tld/faces"
+ xmlns:ui=3D"http://java.sun.com/jsf/facelets"
+ xmlns:c=3D"http://java.sun.com/jstl/core"
+ xmlns:fn=3D"http://java.sun.com/jsp/jstl/functions"
+ xmlns:t=3D"http://myfaces.apache.org/tomahawk"> =
+ =
+ <style type=3D"text/css" media=3D"screen"> =
+ @import "/loginportlet/css/starter.css";
+ @import "/loginportlet/css/uni-form.css";
+ </style>
+
+ <script src=3D"/loginportlet/js/jquery.js" type=3D"text/javascript"&=
gt;</script>
+ <script src=3D"/loginportlet/js/uni-form.jquery.js" type=3D"text/jav=
ascript"></script>
+ =
+ <h:form styleClass=3D"uniForm" >
+ <fieldset class=3D"inlineLabels">
+ <legend>Sign in</legend> =
+
+ <div class=3D"ctrlHolder"> =
+ <h:outputLabel for=3D"login" style=3D"width: 70px"><e=
m>*</em>Login:</h:outputLabel>
+ <h:inputText id=3D"login" value=3D"#{loginBean.login}" requ=
ired=3D"true" styleClass=3D"textInput" /> =
+ <h:message for=3D"login" styleClass=3D"portlet-msg-error" /=
>
+ </div>
+ <div class=3D"ctrlHolder"> =
+ <h:outputLabel for=3D"password" style=3D"width: 70px">&l=
t;em>*</em>Password:</h:outputLabel>
+ <h:inputSecret id=3D"password" value=3D"#{loginBean.passwd}=
" required=3D"true" styleClass=3D"textInput" />
+ <h:message for=3D"password" styleClass=3D"portlet-msg-error=
" /> =
+ </div> =
+ </fieldset>
+ =
+ <div class=3D"buttonHolder" style=3D"margin-top: 20px; margin-rig=
ht: 20px">
+ <h:commandButton styleClass=3D"primaryAction" value=3D"Submit"=
action=3D"#{loginBean.login}" /> =
+ </div>
+ </h:form>
+</f:view>
+
+ The interesting part resides in the backing bean which impleme=
nts
+ the login action triggered when the user clicks the login form submit
+ button.
+
+ package org.exoplatform.loginportlet;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Controller;
+
+(a)Controller
+(a)Scope("request")
+public class LoginBean {
+
+ String login;
+
+ String passwd;
+
+ public String login() throws Exception {
+ String redirect =3D "/portal/j_spring_security_check?j_username=3D=
" + login + "&j_password=3D" + passwd;
+ PortalUtils.sendRedirect(redirect); =
+ return null;
+ }
+
+ ...
+}
+
+ The login action simply sends a HTTP redirect to the spring
+ security login URL passing the user login and password as parameters.
+ This URL informs the filter to try to authenticate the supplied user
+ credentials. This is the Spring security authentication process entry
+ point.
+
+
+
+ Setting up the login portal page
+
+ Now that we have a login portlet available we need to set it up
+ into a portal page.
+
+
+
+ Log in as root in exo portal.
+
+
+
+ Go to application registry and import the loginportlet
+
+
+
+ Add a new hidden page named 'Login' under the portal class=
ic's
+ navigation (read more on page creation here>WCM.Tutorial). Make=
sure
+ that the visible flag is unchecked to hide the page. Also declare
+ the page as public so that everyone can access it without being
+ authenticated for obvious reasons.
+
+
+
+ Finally, drag & drop the login portlet in the page with
+ the desired layout.
+
+
+
+
+
+ Customization of portal login and logout urls
+
+ In the portal header there is a login or logout action display=
ed
+ depending whether you are already logged in or not. We need to custo=
mize
+ those actions so that when the user clicks on it she or he will be
+ redirected either to our login page or to the spring security logout
+ url. Edit the article, go to the default.js tab and apply the follow=
ing
+ changes to the code:
+
+ function validateUser() {
+
+ var user =3D eXo.env.portal.userName;
+ var rootObj =3D document.getElementById("classic-access");
+ var loginContentObj =3D eXo.core.DOMUtil.findFirstDescendantByClass(ro=
otObj, "div", "UIWCMLoginPortlet");
+ var welcomeObj =3D eXo.core.DOMUtil.findFirstDescendantByClass(rootObj=
, "span", "Welcome");
+ var userObj =3D eXo.core.DOMUtil.findFirstDescendantByClass(rootObj, "=
span", "LoggedUser");
+ var languageObj =3D eXo.core.DOMUtil.findFirstDescendantByClass(rootOb=
j, "a", "LanguageIcon");
+ var logXXXObj =3D eXo.core.DOMUtil.findPreviousElementByTagName(langua=
geObj, "a");
+
+ if (user !=3D "null") {
+ welcomeObj.innerHTML =3D "Welcome: "; =
+ userObj.innerHTML =3D user;
+ logXXXObj.innerHTML =3D "Logout";
+ if (eXo.core.DOMUtil.hasClass(logXXXObj, "LoginIcon")) {
+ eXo.core.DOMUtil.removeClass(logXXXObj, "LoginIcon");
+ eXo.core.DOMUtil.addClass(logXXXObj, "LogoutIcon");
+ }
+ logXXXObj.onclick =3D function() { document.location.href =3D '/po=
rtal/j_spring_security_logout' }
+ } else {
+ if (eXo.core.DOMUtil.hasClass(logXXXObj, "LogoutIcon")) {
+ eXo.core.DOMUtil.removeClass(logXXXObj, "LogoutIcon");
+ eXo.core.DOMUtil.addClass(logXXXObj, "LoginIcon");
+ }
+ logXXXObj.innerHTML =3D "Login";
+ logXXXObj.onclick =3D function() { document.location.href =3D '/po=
rtal/public/classic/Login' };
+ }
+
+ languageObj.onclick =3D function () { if(document.getElementById('UIMa=
skWorkspace')) ajaxGet(eXo.env.server.createPortalURL('UIPortal', 'ChangeLa=
nguage', true)); }
+}
+
+eXo.core.Browser.addOnLoadCallback("validateUser", validateUser);
+
+ As you can see, the two onclick event handler function bodies =
have
+ been changed to a simple redirect to the login page or the logout
+ URL.
+
+
+
+ A look at the login page
+
+ Once you are done with all this, just click on the login action
+ and you should be redirect to the login page looking something like
+ that:
+
+
+
+
+
+
+
+
+
+
+ Integration strategies
+
+ Until now we haven't discussed about any integration strategies
+ concerning a potential existing security realm outside of the eXo
+ platform. To address this problem we have the choice between at least =
two
+ different strategies:
+
+ 1.1.1 Direct integration We c=
an
+ directly integrate eXo with the external realm. Everything related to
+ organisation and user management in exo is cleanly separated in its own
+ abstraction accessible through the OrganisationService. The authentica=
tion
+ process itself is encapsulated in the Authenticator abstraction which =
sits
+ on top of the organization service. eXo provides several implementatio=
ns
+ of both. So whether your realm is based on LDAP or JDBC and because the
+ default implementations are generic enough, you will be able to use th=
em
+ and fits them to your needs with a matter of a little configuration. Y=
ou
+ can even develop a custom implementation to meet your more specific
+ needs.
+
+
+ Replication
+
+ Or we can go through a replication process between the external
+ realm and the eXo platform realm. This is the strategy that we are g=
oing
+ to use to build our login portlet example. Furthermore the replicati=
on
+ will occur dynamically on any user authentication attempt.
+
+
+
+
+ Integration with eXo portal
+
+ Being successfully authenticated against an external realm is not
+ sufficient by itself. We also need to propagate the newly created secu=
rity
+ context to the portal own security mechanism. In eXo portal terminolog=
y,
+ it means we have to create an Identity object for the user and registe=
r it
+ into the Identity Registry.
+
+ Spring framework provides a simple notification model where a be=
an
+ can listen to application events published by other beans. Fortunately
+ spring security uses this mechanism and publishes an
+ InteractiveAuthenticationSuccessEvent in case of successful
+ authentication. That will allow us to hook up custom code to that
+ event.
+
+ Furthermore, we need to replicate the user details from the exte=
rnal
+ realm to the eXo portal one according to the integration strategy defi=
ned
+ above.
+
+ We create a SpringSecurityEventHandler bean that implements the
+ ApplicationListener interface and listens to the
+ InteractiveAuthenticationSuccessEvent event.
+
+ package org.exoplatform.spring.security.web;
+
+...
+
+public class SpringSecurityEventHandler implements ApplicationListener {
+
+ private String portalContainerName =3D "portal";
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof InteractiveAuthenticationSuccessEvent) {
+ try {
+ InteractiveAuthenticationSuccessEvent successEvent =3D (In=
teractiveAuthenticationSuccessEvent) event;
+ ExoContainer container =3D getContainer();
+
+ String login =3D successEvent.getAuthentication().getName(=
);
+ String passwd =3D successEvent.getAuthentication().getCred=
entials().toString();
+
+ IdentityRegistry identityRegistry =3D (IdentityRegistry) c=
ontainer.getComponentInstanceOfType(IdentityRegistry.class);
+ Authenticator authenticator =3D (Authenticator) container.=
getComponentInstanceOfType(Authenticator.class);
+ OrganizationService orgService =3D (OrganizationService) c=
ontainer.getComponentInstanceOfType(OrganizationService.class);
+
+ User user =3D orgService.getUserHandler().findUserByName(l=
ogin);
+ if (user =3D=3D null) {
+ user =3D orgService.getUserHandler().createUserInstanc=
e(login); =
+ user.setFirstName(login);
+ user.setLastName(login);
+ orgService.getUserHandler().createUser(user, false); =
+ orgService.getUserHandler().saveUser(user, false);
+ //TODO: put some more integration code here
+ }
+
+ Identity identity =3D authenticator.createIdentity(login);
+
+ Subject subject =3D new Subject();
+ subject.getPrivateCredentials().add(passwd);
+ subject.getPublicCredentials().add(new UsernameCredential(=
login));
+
+ identity.setSubject(subject);
+ identityRegistry.register(identity);
+
+ } catch (Exception e) {
+ e.getMessage();
+ }
+ }
+ }
+
+ protected ExoContainer getContainer() {
+ // TODO set correct current container
+ ExoContainer container =3D ExoContainerContext.getCurrentContainer=
();
+ if (container instanceof RootContainer) {
+ container =3D RootContainer.getInstance().getPortalContainer(p=
ortalContainerName);
+ }
+ return container;
+ }
+
+...
+
+}
+
+ Basically the bean retrieves user login and password from the
+ InteractiveAuthenticationSuccessEvent object and tries to get the user
+ from the organization service. In case he cannot find it in the
+ repository, he simply creates it on the fly. In this example the user =
is
+ created with just a few details, but you can put some custom integrati=
on
+ code with the external realm here, and create the user with all the
+ details (email, birth date, roles, etc.) it seems appropriate to you.
+ After that, the bean creates an Identity object with the help of the
+ authenticator service, populates it with a subject containing the user
+ credentials and registers it. That's all we have to do to make the por=
tal
+ aware of the user logging in.
+
+ Registering our bean is done the usual way in security-context.x=
ml
+ file:
+
+ ...
+<beans:bean id=3D"myEventHandler" class=3D"org.exoplatform.spring.secur=
ity.web.SpringSecurityEventHandler" />
+...
+
+
+
+ Security context propagation to portlets
+
+ Part of the problem is the question of security context propagat=
ion
+ between on one side the portal webapp and at the other side the portle=
ts
+ webapps. This means that the security context has to be available in t=
he
+ portlet side allowing the application logic to deal the with current u=
ser
+ principal and granted authorities. By default Spring security uses a
+ thread local variable to partially achieve this. But a problem may ari=
se
+ due to the fact that the portal invokes the portlet through a webapp c=
ross
+ context call. This means that it can lead to a class cast exceptions (=
two
+ different classloaders involved), or that the security context is simp=
ly
+ not propagated at all. To accommodate this we will need to set up two
+ request filters, one at the portal webapp side and the other at the
+ portlet webapp side and use the http request to propagate the context =
in
+ between.
+
+
+ Portal side filter
+
+ We will use the spring security extensible filter chain to plu=
g in
+ our filter.
+
+ package org.exoplatform.spring.security.web;
+
+...
+
+public class PortalSideSecurityContextFilter extends SpringSecurityFilter {
+
+ @Override
+ protected void doFilterHttp(HttpServletRequest request, HttpServletRes=
ponse response, FilterChain chain) throws IOException, ServletException {
+ //fill request with security context
+ SecurityContext context =3D SecurityContextHolder.getContext(); =
=
+ request.setAttribute(HttpSessionContextIntegrationFilter.SPRING_S=
ECURITY_CONTEXT_KEY, context); =
+ =
+ //fill request with security last exception
+ Object e =3D request.getSession().getAttribute(AbstractProcessing=
Filter.SPRING_SECURITY_LAST_EXCEPTION_KEY);
+ request.setAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST=
_EXCEPTION_KEY, e);
+ =
+ chain.doFilter(request, response);
+ }
+
+ public int getOrder() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+}
+
+ The PortalSideSecurityContextFilter simply fills the request w=
ith
+ the security context and security last exception using the
+ HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY and
+ AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY attribute
+ names. The portlet can have a look to the
+ AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY attribut=
e to
+ check if a security exception has occured.
+
+ The following lines in the security-context file register our
+ custom filter in the chain at the last position.
+
+ ...
+ <beans:bean id=3D"myCustomFilter" class=3D"org.exoplatform.spring.se=
curity.web.PortalSideSecurityContextFilter">
+ <custom-filter after=3D"LAST" />
+ </beans:bean>
+...
+
+
+
+ Portlet side filter
+
+ In the portlet webapp we create a regular filter named
+ PortletSideSecurityContextFilter.
+
+ package org.exoplatform.spring.security.web;
+
+...
+
+public class PortletSideSecurityContextFilter implements Filter {
+
+ public void destroy() { =
+ =
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response,=
FilterChain filterChain) throws IOException, ServletException {
+ Object object =3D request.getAttribute(HttpSessionContextIntegrati=
onFilter.SPRING_SECURITY_CONTEXT_KEY);
+ SecurityContext context =3D (SecurityContext) serializeDeserialize=
(object);
+ if (context !=3D null) {
+ SecurityContextHolder.setContext(context);
+ } else {
+ SecurityContextHolder.clearContext();
+ } =
+ =
+ filterChain.doFilter(request, response);
+ }
+
+ public void init(FilterConfig arg0) throws ServletException { =
+ =
+ }
+
+ private Object serializeDeserialize(Object obj) {
+ Object result =3D null; =
+ try {
+ ByteArrayOutputStream bout =3D new ByteArrayOutputStream();
+ ObjectOutputStream out =3D new ObjectOutputStream(bout);
+
+ out.writeObject(obj);
+
+ ByteArrayInputStream bin =3D new ByteArrayInputStream(bout.=
toByteArray());
+ ObjectInputStream in =3D new ObjectInputStream(bin);
+
+ result =3D in.readObject(); =
+ } catch (Exception e) {
+ //TODO: handle exception
+ }
+ return result;
+ }
+ =
+}
+
+ The PortletSideSecurityContextFilter retrieves the security
+ context from the request and proceeds to a serialization
+ de-serialization of it to avoid a potential class cast exception that
+ may occur when propagating an object across webapps. Then the contex=
t is
+ simply set or cleared whether the context is null or not.
+
+ To register your filter simply add the following lines to your
+ portlet webapp web.xml file.
+
+ ...
+ <filter>
+ <filter-name>portletSideSecurityContextFilter</filter-name&=
gt;
+ <filter-class>org.exoplatform.spring.security.web.PortletSideS=
ecurityContextFilter</filter-class>
+ </filter>
+ =
+ <filter-mapping>
+ <filter-name>portletSideSecurityContextFilter</filter-name&=
gt;
+ <url-pattern>/*</url-pattern>
+ <dispatcher>REQUEST</dispatcher>
+ <dispatcher>INCLUDE</dispatcher>
+ <dispatcher>FORWARD</dispatcher>
+ </filter-mapping>
+...
+
+
+
+
+ Conclusion
+
+ We are done! Now we know how to integrate the spring security
+ framework in the eXo portal. Thanks to the the great integration
+ capabilities of both eXo portal and Spring framework. You can have a l=
ook
+ to the attachment section on this page and get the source code of this
+ tutorial.
+
+
Modified: jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modu=
les/core.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re.xml 2010-07-30 13:29:37 UTC (rev 2845)
+++ jcr/branches/1.12.x/docs/reference/en/src/main/docbook/en-US/modules/co=
re.xml 2010-07-30 15:13:44 UTC (rev 2846)
@@ -8,8 +8,41 @@
=
-
+
=
+
+
+
+
+ =
+
+ =
=
+
+
+
+ =
+ =
+
+
+ =
=
+ =
+ =
=
+ =
+ =
+
+ =
+ =
+ =
+
Added: jcr/branches/1.12.x/docs/reference/en/src/main/resources/images/logi=
n-page.jpg
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)
Property changes on: jcr/branches/1.12.x/docs/reference/en/src/main/resourc=
es/images/login-page.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jcr/branches/1.12.x/docs/reference/en/src/main/resources/images/orga=
nization-exo.jpg
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)
Property changes on: jcr/branches/1.12.x/docs/reference/en/src/main/resourc=
es/images/organization-exo.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
--===============0903027441959976257==--