The first step in interacting with Crystal Enterprise from an SDK perspective is to establish an active session with CE. This is done via the SessionMgr (Session Manager) object. The result of logging on is an EnterpriseSession object, which provides an entry point into all the SDK operations. There are several ways the logon can happen; the following sections describe these methods.
This is a fairly straightforward two-step procedure. First, the SessionMgr object must be created. Then its Logon method must be invoked, passing in four parameters:
As discussed in Chapter 24, "Crystal Enterprise Architecture," Crystal Enterprise has several different types of authentication modes it supports, including the following:
For more information on types of supported authentication modes, p. 515
To indicate which authentication mode to use, pass in the authentication type identifierlisted above in parentheses as the last argument to the Logon method. The return value of the Logon method is an EnterpriseSession object. Listing 34.1 shows a sample code listing that logs on a user named Ryan, with a password of 123 to a CMS named CMS1 using Crystal Enterprise authentication.
<% Create the session manager Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") Log on to the system Set sess = sessMgr.Logon("Ryan", "123", "CMS1", "secEnterprise") %>
Listing 34.1 was made to be simple and easy to follow but in the real world, it wouldn be a good practice to hard-code the username and password. Listing 34.2 illustrates how a developer might prompt the user to type in their username and password. LogonPrompt.htm provides the user interface for the logon, and it performs a form post to Logon.asp to perform the logon (see Listing 34.3).
<% usr = Request.Form("username") pwd = Request.Form("password") Set sessMgr = CreateObject("CrystalEnterprise.SessionMgr") Set sess = sessMgr.Logon(usr, pwd, "CMS1", "secEnterprise") %>
The interactive logon is better than a hard-coded logon, but still not always ideal, especially if its running as a reporting module inside a surrounding application that the user has already logged in to. A desirable behavior would be to log the user on behind the scenes. This is accomplished by simply reading the username and password from a location such as a database, encrypted cookie, or Session variable as shown in Listing 34.4.
<% usr = Session("username") pwd = Session("password") Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") Set sess = sessMgr.Logon(usr, pwd, "CMS1", "secEnterprise") %>
The name of the CMS will likely change because an application often is moved from environment to environment (that is, from developers machine to test server to production server). A good practice is when calling the Logon method, don hard-code the CMS name but rather read it from a variable stored somewhere: a Registry key, a configuration file, and so on. This way, the code doesn need to be modified when moving to a different environment.
Although the previous examples were simple and effective, a Crystal Enterprise administrator most likely does not want to create accounts manually for every user and have her log on using Crystal Enterprise Authentication. Instead, it is likely that Crystal Enterprise will be pointed to an external security mechanism such as Active Directory. In this case, the application can still pass the Active Directory username and password as arguments to the Logon method as shown in Listing 34.5.
<% Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") Set sess = sessMgr.Logon("RyanM", "abcxyz", "CMS1", "secWinAD") %>
Although this works, the probable desirable behavior is to log the user on without having to hard-code credentials or having the user type them in. Instead the user is logged on silently based on the current user account logged onto the clients workstation. This is called Single Sign On. From an SDK perspective, Single Sign On is very simple: pass blank strings for the username and password, as shown in Listing 34.6.
<% Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") Set sess = sessMgr.Logon("", "", "CMS1", "secWinAD") %>
This is simple from a coding point of view, but there is some server configuration needed before this runs successfully. The Crystal Enterprise documentation has a section on Single Sign On and provides step-by-step instructions on what settings to change, but at a high level, they are listed here:
Single Sign On is only supported with the Windows NT (secWindowsNT) and Active Directory (secWinAD) authentication modes. It is not supported with LDAP (secLDAP).
So far, the sample code in this chapter has consisted of just a single ASP page. In a real-world application, there would be many ASP pages involved. Based on standard rules of ASP, all objects created during the processing of the page are destroyed when the page has finished delivering its output. Because the EnterpriseSession object represents a Crystal Enterprise session, the session is lost and terminated when this object is destroyed. If another ASP page needed to access the Crystal Enterprise SDK, it would need a way to access the Crystal Enterprise session that was used previously. There are multiple ways to handle this.
The first approach to solving this problem would be to store the EnterpriseSession object in an ASP Session variable that could be accessed later. This is shown in Listings 34.7 and 34.8.
<% Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") Set sess = sessMgr.Logon("Ryan", "123", "CMS1", "secEnterprise") Set Session("CE-Session") = sess %>
<% Set sess = Session("CE-Session") %>
This approach is easy to implement and can work given the following conditions:
When the application gets larger and there are reasons why Session variables are not attractive or possible, you can use the last method of logging on: a logon token.
If an ASP Session variable was not used, each ASP page would need to log on again using the username and password. This would be an expensive operation from a performance perspective. A better way to handle this would be to log the user on and then ask Crystal Enterprise to generate a token that can be used to log on again later. This token could be stored in a cookie, hidden form field, or on the query string.
Using a logon token is a two-step process. First, the token needs to be generated. This is done using the LogonTokenMgr object. Listing 34.9 creates a token and stores it in a cookie.
<% Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") Set sess = sessMgr.Logon("Ryan", "123", "CMS1", "secEnterprise") token = sess.LogonTokenMgr.DefaultToken Response.Cookies("CE-Logon-Token") = token %>
When control passes to a new ASP page, the token can be retrieved from the cookie and used to log on. Instead of using the Logon method, the LogonWithToken method is used (see Listing 34.10).
<% Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") token = Request.Cookies("CE-Logon-Token") Set sess = sessMgr.LogonWithToken(token) %>
In Listing 34.9, the token is generated by accessing the DefaultToken property of the LogonTokenMgr object. This is the simplest way to generate a token but doesn provide control over how long that token can be used. A more granular way of generating a token is to call the CreateLogonTokenEx method. It takes the following parameters:
Listing 34.11 shows this in action.
<% Set sessMgr = Server.CreateObject("CrystalEnterprise.SessionMgr") Set sess = sessMgr.Logon("Ryan", "123", "CMS1", "secEnterprise") token = sess.LogonTokenMgrEx.CreateLogonToken("WEB1", 60, 25) Response.Cookies("CE-Logon-Token") = token %>