WebCenter Sites provides authentication functionality through the USER
tags, user profile management through the DIR
tags, and enforces security on database tables and rendered pages through access control lists (ACLs). You use these user management and security mechanisms to manage users and control visitor access on your distribution system and on your WebCenter Sites development and management systems.
This chapter contains the following sections:
Section 31.2, "Controlling Visitor Access to Your Online Sites"
Section 31.5, "Visitor Access in the Burlington Financial Sample Site"
The Directory Services API enables your WebCenter Sites system to connect to directory servers that contain authentication information, user information, and so on.
WebCenter Sites delivers three directory services plug-ins, one of which was installed when your WebCenter Sites systems were installed:
The WebCenter Sites directory services plug-in, which uses the native WebCenter Sites user management tables; that is, the SystemUsers
and SystemUserAttrs
tables
The LDAP plug-in, which actually supports any JNDI server
The NT plug-in, which retrieves user credentials and login name from the NT directory but gets all other user information from the SystemUserAttrs
table
The plug-in is installed during the installation of your WebCenter Sites systems and it is configured by setting properties in the dir.ini
file. For information about configuring your user management setup, see the Oracle Fusion Middleware WebCenter Sites Administrator's Guide.
This section contains the following topics:
A directory entry is a named object with assigned attributes, in particular, user and group type entries:
A user type object has a distinguished name and a set of attributes such as commonname, username, password and email.
A group type object, similar to a WebCenter Sites ACL, also has a distinguished name and a set of attributes.
Names reflect the hierarchy in which they are associated; to ensure portability across directory implementations, names should be treated as opaque strings.
Some directory databases organize entries using a hierarchical structure. With WebCenter Sites's directory services API, an entry's attributes and its place in the hierarchy are distinct. As a result, retrieving an entry's attributes does not yield information about its children.
Support for hierarchies depends on the underlying directory implementation; for example, LDAP directories support a hierarchical structure, while WebCenter Sites's native directory database does not support a hierarchical structure.
To ensure portability across directory implementations, your code should not assume support for hierarchical data.
Group hierarchies do not affect internal WebCenter Sites permissions.
WebCenter Sites's directory services API does not enforce referential integrity. When you delete a user with the directory tags, your application must ensure that group memberships are also deleted, by first removing the user from the groups that he is associated with.
When a member is added to a group, the JNDI implementation always builds a fully distinguished name for the value of the uniquemember
attribute, regardless of the name passed into the addmember
tag.
WebCenter Sites delivers the DIR
tag family, with both XML and JSP versions, that you can use to invoke the Directory Services API.
The DIR
tags are as follows:
Tag | Description |
---|---|
|
Adds attributes to an existing entry (which can be either a user or a group). |
|
Adds a member to a group (usually a user). |
|
Retrieves the child entries for a specified parent in a list variable. |
|
Creates a directory entry. |
|
Deletes a directory entry. |
|
Gets the attribute values for a specified entry in a list variable. |
|
Lists the members of a specified group. |
|
Lists all the groups that an entry (either a group or a user) belongs to. |
|
Returns a list of all the users in the directory. |
|
Deletes an attribute value for an entry. |
|
Removes an entry from a group. |
|
Replaces the value of an attribute for an entry (either a user or a group). |
|
Searches the directory for entries who match the specified search criteria. |
Regardless of whether the directory is implemented with LDAP, WebCenter Sites only, or any other directory server, the code you write with the DIR
tags is very similar.
For more information about these tags, see the Oracle Fusion Middleware WebCenter Sites Tag Reference. For code samples, see Section 31.1.5.4, "Directory Services Code Samples."
Some of the WebCenter Sites Directory Services tags write information to the database. If your database administrators will be handling all of the website's write operations, such as adding user information to the database, restrict use of the directory tags to
read-only operations. This policy avoids synchronization issues with third-party directory administration tools.
The read-only operations are presented in this section. Operations are performed using the credentials and read permissions of the currently authenticated user.
Due to limitations in some directory servers, search is not allowed from the top organizational level. To avoid portability issues, always specify the context attribute on the DIR.SEARCH tag.
Looking up a user generally involves two steps:
Call DIR.SEARCH
on the userid
to get the entry name.
Call DIR.GETATTRS
to get the attributes of the user in question.
It is recommended that you use one of the following three methods to list users:
For small user databases, use the DIR.LISTUSERS
tag, which recursively lists all users under the peopleParent
property. This tag is inefficient on large user databases.
For large user databases, use the DIR.CHILDREN
tag to walk the hierarchy. The DIR.CHILDREN
tag is best used for group types and not for user types.
For user databases with a flat hierarchy, narrow results with a search
The following JSP code sample illustrates some possible directory operations:
<% String sMainTestUserName = "ContentServer"; String sMainTestUserPW="FutureTense"; String sPeopleParent = ics.GetProperty("peopleparent", "dir.ini", true); String sGroupParent = ics.GetProperty("groupparent", "dir.ini", true); String sUsername = ics.GetProperty("username", "dir.ini", true); String sCommonName = ics.GetProperty("cn", "dir.ini", true); IList mylist; %> <user:su username='<%=sMainTestUserName%>' password='<%=sMainTestUserPW%>'> <H2>List All Users</H2> <ics:clearerrno/> <dir:listusers list='mylist'/> <br> <b>dir:listusers errno: <ics:getvar name='errno'/></b> <ics:listloop listname='mylist'> <br><ics:listget listname='mylist' fieldname='NAME'/> </ics:listloop> <H2>Look Up the ContentServer User by Username</H2> <ics:clearerrno/> <dir:search list='mylist' context='<%=sPeopleParent%>'> <dir:argument name='<%=sUsername%>' value='ContentServer'/> </dir:search> <br><b>dir:search errno: <ics:getvar name='errno'/></b> <% mylist = ics.GetList("mylist"); if(mylist.numRows() != 1) { out.print("<br>Error finding entry."); } mylist.moveTo(1); ics.SetVar("ContentServerDn", mylist.getValue("NAME")); %> <H2>Show ContentServer Attributes</H2> <ics:clearerrno/> <dir:getattrs list='mylist' name='<%=ics.GetVar("ContentServerDn")%>'/> <br><b>dir:getattrs errno: <ics:getvar name='errno'/></b> <ics:listloop listname='mylist'> <br> <ics:listget listname='mylist' fieldname='NAME'/>= <ics:listget listname='mylist' fieldname='VALUE'/> </ics:listloop> <H2>Show Group Memberships for ContentServer</H2> <ics:clearerrno/> <dir:groupmemberships name='<%=ics.GetVar("ContentServerDn")%>' list='mylist'/> <br><b>dir:groupmemberships errno: <ics:getvar name='errno'/></b> <ics:listloop listname='mylist'> <br> <ics:listget listname='mylist' fieldname='NAME'/> </ics:listloop> <H2>Lookup the SiteGod Group by CommonName</H2> <ics:clearerrno/> <dir:search list='mylist' context='<%=sGroupParent%>'> <dir:argument name='<%=sCommonName%>' value='SiteGod'/> </dir:search> <br><b>dir:search errno: <ics:getvar name='errno'/></b> <% mylist = ics.GetList("mylist"); if(mylist.numRows() != 1) { out.print("<br>Error finding entry."); } mylist.moveTo(1); ics.SetVar("SiteGodDn", mylist.getValue("NAME")); %> <H2>Show SiteGod Attributes</H2> <ics:clearerrno/> <dir:getattrs list='mylist' name='<%=ics.GetVar("SiteGodDn")%>'/> <br> <b>dir:getattrs errno: <ics:getvar name='errno'/></b> <ics:listloop listname='mylist'> <br> <ics:listget listname='mylist' fieldname='NAME'/>= <ics:listget listname='mylist' fieldname='VALUE'/> </ics:listloop> <H2>Show SiteGod Group Members</H2> <ics:clearerrno/> <dir:groupmembers name='<%=ics.GetVar("SiteGodDn")%>' list='mylist2'/> <br> <b>dir:groupmembers errno: <ics:getvar name='errno'/></b> <ics:listloop listname='mylist2'> <br> <ics:listget listname='mylist2' fieldname='NAME'/> </ics:listloop> <H2>Children of groupparent </H2> <ics:clearerrno/> <dir:children name='<%=sGroupParent%>' list='mylist'/> <br> <b>dir:children errno: <ics:getvar name='errno'/></b> <ics:listloop listname='mylist'> <br> <ics:listget listname='mylist' fieldname='NAME'/> </ics:listloop> </user:su>
Any of the directory tags can cause a range of directory errors to be set. See the Oracle Fusion Middleware WebCenter Sites Tag Reference for a comprehensive list of directory services error messages.
Your directory services code should handle every one of the error codes listed for a given tag call. This is necessary to support the J2EE JNDI interface.
The first step in troubleshooting directory services applications is to check the error log (in the WebCenter Sites log file).
You enable directory services logging by setting the log.filterLevel
property (found in the logging.ini
property file). There are seven levels of error messages that you can view:
fatal
, which logs fatal level messages
severe
, which logs severe and fatal level messages
error
, which logs error and fatal level messages
warning
, which logs warning and fatal level messages
info
, which logs warning, error, severe, and fatal level messages
trace, which logs trace messages
detail, which logs all types of messages
During troubleshooting, trace
is the most verbose setting, and as a result, has the highest performance impact.
Directory services log entries use the following format:
[<timestamp>][Directory-<severity>-<errno>] [<class>:<method>][<message>][<session id>]
For example:
[Jan 17, 2002 1:49:44 PM][Directory-T] [BaseFactory:instantiateImplementation(ICS,String,Class[], Object[])][Instantiating:com.openmarket.directory.common.Factory] [PEccxyF1Ueh7zYvjNgg4D6bqZzf0llfWMaiBimIN9H1Z9KomDcPy]
The previous message is a trace (T), and thus has no associated errno
value.
For information about error logging, see Chapter 10, "Error Logging and Debugging."
A common problem for LDAP implementations is incorrectly specified permissions on the directory server. If the error log indicates a permission problem, ensure that the authenticated user has permissions to execute the requested operation by checking the permission settings on the directory server. Try logging into the directory server directly (outside of WebCenter Sites) and performing the same action to ensure that permissions are correctly set. After checking the log and permissions, you can often resolve a configuration error by examining the property files.
For property descriptions and values, see the Oracle Fusion Middleware WebCenter Sites Property Files Reference.
WebCenter Sites manages users through access control lists (ACLs). By using ACLs, you can restrict access to tables in the WebCenter Sites database and the rendered pages served on your sites by WebCenter Sites.
If you design an online site where visitors log in with user names and passwords, you can associate registered visitors with one or more ACLs.
When a visitor first visits a site, WebCenter Sites creates a session and implicitly logs in the visitor as the standard default user, DefaultReader. The identity of a visitor is updated (and any associated ACLs go into effect) when a USER.LOGIN
command is used and the visitor is authenticated against a password.
This section contains the following topics:
WebCenter Sites provides a set of access control list tags (both XML and JSP versions) that you can use to create ACLs. You can use either the WebCenter Sites interface on the delivery system or the WebCenter Sites ACL tags to create the ACLs that you need for your visitor accounts on your delivery system.
The following table lists the ACL tags:
Tag | Description |
---|---|
|
Creates an ACL |
|
Deletes an ACL |
|
Gathers fields into an ACL |
|
Copies a field from an ACL |
|
Retrieves a list of ACLs |
|
Loads an ACL |
|
Saves an ACL |
|
Scatters a field from an ACL |
|
Sets a field in an ACL |
For more information:
ACL tags: See the Oracle Fusion Middleware WebCenter Sites Tag Reference.
ACLs in general: See the Oracle Fusion Middleware WebCenter Sites: Administrator's Guide.
WebCenter Sites also provides the following USER
tags (both XML and JSP versions) that you use on pages that log users in and out.
The USER
tags are as follows:
Tag | Description |
---|---|
|
Logs a user in. |
|
Logs a user out. |
|
Logs the user in as a specific user in order to perform an operation such as creating an account or edit a user profile. |
For more information about these tags, see the Oracle Fusion Middleware WebCenter Sites Tag Reference.
WebCenter Sites includes a default key for encrypting passwords and other sensitive information. You can specify your own encryption key by using the Utilities
class encryptString
method. See the Oracle Fusion Middleware WebCenter Sites Java API Reference for information about Java methods that deal with encryption.
WebCenter Sites also supports Secure Sockets Layer (SSL), which allows encryption of information going to and from your web servers. For more information about WebCenter Sites and SSL, see the Oracle Fusion Middleware WebCenter Sites Administrator's Guide.
This section provides simple code samples that illustrate how to code login forms that prompt a visitor to log in and then authenticate the user name and password.
This example presents code from the following elements:
PromptForLogin
: XML element that displays a form that requests a username and password
Login
: XML element that authenticates the username and password combination passed to it from the PromptForLogin
element
This section contains the following topics:
The PromptForLogin
element displays a form that asks a visitor to enter two pieces of information: username and password.
The code that creates the form follows:
<DIV ALIGN="center"> <FORM ACTION="ContentServer" METHOD="post"> <INPUT TYPE="hidden" NAME="pagename" VALUE="CSGuide/Security/Login"/> <TABLE CELLPADDING="5" CELLSPACING="5"> <TR> <TH ALIGN="right">Name</TH> <TD><INPUT TYPE="text" NAME="username" SIZE="16"/></TD> </TR> <TR> <TH ALIGN="right">Password</TH> <TD><INPUT TYPE="password" NAME="password" SIZE="16"/></TD> </TR> <TR> <TD> </TD> <TD ALIGN="center"><INPUT TYPE="submit" NAME="doit" VALUE="Login"/></TD> </TR> </TABLE> </FORM> </DIV>
The visitor fills in the form and clicks the Submit button. The information gathered in the form and the page name of the Login
page (see the first input type
statement, above) is sent to the browser. The browser sends the page name to WebCenter Sites, WebCenter Sites looks it up in the SiteCatalog
table and then invokes that page entry's root element.
There can only be one root element for a WebCenter Sites page (that is, an entry in the SiteCatalog
table). The root element for the Login page
is the Login.xml
element.
The Login
element attempts to log the visitor in and then to authenticate the visitor by using the USERISMEMBER
tag to determine whether the visitor has any of the required ACLs.
This element does the following:
Logs the visitor in with the USER.LOGIN
tag and checks to see if there was an error.
Sets a variable list that holds a list of ACLs to compare the visitor's credentials against.
Checks the visitor's ACLs assignments against the list variable with the USERISMEMBER
tag
The following sample code authenticates the visitor:
<SETVAR NAME="errno" VALUE="0"/> <USER.LOGIN USERNAME="Variables.username" PASSWORD="Variables.password"/> <IF COND="Variables.errno=0"> <THEN> <H3>Welcome <CSVAR NAME="Variables.username"/></H3> <!-- Next, create a variable named aclToCheck and set it to hold the ACLs that the visitor needs to progress any further on the site. This variable can be set to one ACL or to a comma-separated list of ACLs, as in this example--> <SETVAR NAME="aclToCheck" VALUE="ContentCustomer,SiteGod"/> <SETVAR NAME="errno" VALUE="0"/> <USERISMEMBER GROUP="Variables.aclToCheck"/> <IF COND="Variables.errno=1"> <THEN> <P>You are a member of the at least one of the following acls: <CSVAR NAME="Variables.aclToCheck"/></P> </THEN> <ELSE> <P>Sorry, you are not a member of any of the following acls: <CSVAR NAME="Variables.aclToCheck"/></P> </ELSE> </IF> </THEN> <ELSE> <H3>Sorry, can't find your credentials.</H3> </ELSE> </IF>
This section provides simple code samples that illustrate how to code forms that prompt a visitor to register (obtain a user account) and then create a user account for that visitor.
This example presents code from the following elements:
PromptForNew Account
: XML element that displays a form that requests the visitor to enter the user name and password that he or she would like to use
CreateAccount
: JSP element that creates the new account
This section contains the following topics:
The PromptForNewAccount
element displays a form that prompts the visitor to enter a user name and password and to re-enter the password to confirm it.
Here's the code that creates the form:
<div align="center"> <h3>Create a New Account</h3> <FORM ACTION="ContentServer" METHOD="post"> <input type="hidden" name="pagename" value="CSGuide/Security/CreateAccount"/> <table cellpadding="5" cellspacing="5"> <tr> <th align="right">Pick a username</th> <td><input type="text" name="username" size="16"/></td> </tr> <tr> <th align="right">Pick a password</th> <td><input type="password" name="password" size="16"/></td> </tr> <tr> <th align="right">Confirm your new password</th> <td><input type="password" name="confirm_password" size="16"/></td> </tr> <tr> <td> </td> <td><input type="submit" name="doit" value="Create Account"/></td> </tr> </table> </FORM> </div>
The visitor fills in the form and clicks the Submit button. The information gathered in the form and the page name of the CreateAccount
page (see the first input type
statement, above) is sent to the browser.
The browser sends the page name to WebCenter Sites, WebCenter Sites looks it up in the SiteCatalog
table and then invokes that page entry's root element.
There can only be one root element for a WebCenter Sites page (that is, an entry in the SiteCatalog
table). The root element for the CreateAccount page
is the CreateAccount.jsp
element.
Only someone with SiteGod
or ContentEditor
ACLs can create a new user account. Because of this restriction, the CreateAccount
element does the following:
Logs the visitor in as a privileged user, without the knowledge of the visitor.
Creates the account.
Assigns the new user the appropriate ACLs (every user must belong to at least one ACL)
Here's the code that creates the new user account:
<SETVAR NAME="errno" VALUE="0"/> <!-- switch temporarily to a privileged user --> <!-- The username and password for the privileged user should be encrypted in a property file. You should obtain them from the property file, decrypt them, then pass them it. For this example, they are hard-coded. --> <USER.SU USERNAME="jumpstart" PASSWORD="jumpstart"> <USERISMEMBER GROUP="UserEditor"/> <IF COND="Variables.errno!=1"> <THEN> <h3>An error has occurred creating the account (no UserEditor privs). Contact the webmaster</h3> </THEN> <ELSE> <IF COND="Variables.password!=Variables.confirm_password"> <THEN> <h3>Your passwords do not match. Click the Back button and try again.</h3> </THEN> <ELSE> <!-- Get the parameters from the property file --> <ics.getproperty name="username" file="dir.ini" output="unameattr"/> <ics.getproperty name="password" file="dir.ini" output="passattr"/> <!-- create the user's name in the right format for the dir tags --> <ics.getproperty name="peopleparent" file="dir.ini" output="namebase"/> <name.makechild context="Variables.namebase" output="iname"> <name.argument name="Variables.unameattr" value="Variables.username"/> </name.makechild> <!-- create the user --> <dir.create name="Variables.iname"> <dir.argument name="Variables.unameattr" value="Variables.username"/> <dir.argument name="Variables.passattr" value="Variables.password"/> <!-- additional parameters can be added here but for the example we won't --> <!-- In particular, if you are using LDAP, you will have to spin through and set the values of the properties in the property requiredPeopleAttrs in dir.ini. --> </dir.create> <IF COND="Variables.errno=0"> <THEN> <!-- give the new user an acl and format it correctly for dir.addgroupmember --> <ics.getproperty name="groupparent" file="dir.ini" output="groupparent"/> <ics.getproperty name="cn" file="dir.ini" output="cn"/> <name.makechild context="Variables.groupparent" output="groupid"> <name.argument name="Variables.cn" value="Browser"/> </name.makechild> <!-- add the acl --> <dir.addgroupmember name="Variables.groupid" member="Variables.iname"/> <IF COND="Variables.errno=0"> <THEN> <h3>Success!</h3> </THEN> <ELSE> <h3>User created but error adding user to group. Contact the webmaster</h3> </ELSE> </IF> </THEN> <ELSE> <h3>Error creating user! Contact the webmaster.</h3> </ELSE> </IF> <!-- create success check --> </ELSE> </IF> <!-- passwords match --> </ELSE> </IF> </USER.SU>
The Burlington Financial sample site includes a membership component that uses elements to sign up new members and log in existing members.
These visitor registration elements are not robust enough for use on a real-world website, but can give you a starting point for your own designs. For example, Burlington Financial has sample visitor account screens, allowing visitors to register and set their own preferences, but does not use this information to restrict visitor access to certain web pages, or to make recommendations based on a member's profile.
This section contains the following topics:
Burlington Financial uses a table named bfmembers
to implement the membership component. (This table is created for the sample site when it is installed. None of the WebCenter Sites modules or products use this table.) Although the membership elements add a row to the bfmembers
database table for each new registered member's profile information, they do not add a row to the SystemUsers
table.
There is one generic user, BFUser, for all Burlington Financial members. The name and password are the same (BFUser/BFUser
) and should not be changed. The member login code in Burlington Financial sets a session variable for the visitor, which is then used to identify that visitor.
Because Burlington Financial is a sample site, members' passwords are stored in the bfmembers
table as plain text. A real website would store passwords in encrypted format. Burlington also grants Visitor, BFMember, and Browser ACL privileges to entries added to the bfmembers
table.
There are currently no elements for managing the Burlington Financial accounts. If you want to try editing or deleting members' accounts, use Oracle WebCenter Sites Explorer to modify the bfmembers
table.
There are several elements that handle processing requests for Burlington Financial members. If you have installed the Burlington Financial sample site, you can use Oracle WebCenter Sites Explorer to open and examine them. All but one is located here:
ElementCatalog/BurlingtonFinancial/Util/Account
The AccountAccessScript
element is located here:
ElementCatalog/BurlingtonFinancial/Util
This is a page template that calls pagelet elements for the header, footer, navigation menu, and the account content.
This file contains three JavaScript routines (checkSignupForm
, checkProfileForm
, and checkLoginForm
) that perform basic error checking on the HTML account forms. This is called from Login.xml
, Profile.xml
, and SignUp.xml
elements.
This page calls the Block.xml
article template to render an article of text about the Burlington Financial site. On a real website, the article would contain benefits information.
This page displays the login screen for registered members and calls LoginPost.xml
to handle the login form input. It also calls Benefits.xml
, and SignUp.xml
for non-members.
This pagelet element calls ProcessLogin.xml
to display a login message.
This page displays an editable profile form if the visitor is registered, or else calls SignUp.xml
if the visitor is not registered.
This pagelet element displays an appropriate login message, depending on whether the visitor who submitted the form is a registered member.
This page displays the sign-up screen for non-registered visitors and calls the catalogmanager
to add a row to the bfmembers
table for a new user, or to update the bfmembers
table for an existing user.