DB2 Content Manager 8.2 的單點登入 portlet的配置

genusBIT發表於2009-04-27

簡介

僱員工作空間系列 的第 5 部分和第 6 部分將描述如何建立 Document Management portlet 來訪問 DB2 Content Manger。然而,這兩部分並沒有詳細討論身份驗證。本文將簡要地討論 Document Management portlet 中所實現的身份驗證方法,並展示如何使用另一種身份驗證方法來實現單點登入(single sign-on)功能。

系統環境

文中使用了下列產品:

  • Lotus Workplace for Multiplatforms Version 2.01
  • IBM DB2 Content Manager for Multiplatforms Version 8.2
  • IBM DB2 Information Integrator for Content Version 8.2
  • IBM WebSphere Application Server Version 5.1
  • IBM WebSphere Studio Application Developer Version 5.1.2
  • IBM Portal Toolkit Version 5.0.2
  • IBM DB2 Universal Database Enterprise Version 8.1

本文中的系統環境與僱員工作空間系列中使用的環境之間的主要不同是:我們使用的是 Lotus Workplace 2.01,而非 WebSphere Portal Server 5.0。Lotus Workplace 伺服器 2.0.1 是執行在 WebSphere Portal Server 5.0 之上的應用伺服器。它提供了一個整合的企業工作環境,該環境允許使用者管理郵件、傳送即時訊息和執行 portlet 應用程式。將 Document Management portlet 遷移到 Lotus Workplace 不需要修改任何程式碼。

所有的使用者資訊都儲存在一個 LDAP 使用者登錄檔中,以使 Lotus Workplace 和 DB2 Content Manager 中的使用者資訊保持同步。對於本文中所使用的身份驗證方法來說,這是必需的。

憑證保險庫

DB2 Content Manager Server 是作為後端伺服器與 portlet 整合的,因此當您使用 portlet 訪問 DB2 Content Manager 時,需要在伺服器上進行身份驗證。進行身份驗證的方法之一就是通過使用使用者名稱和密碼來使用 DB2 Content Manager API。在連線 DB2 Content Manager Server 時,portlet 需要提示輸入使用者名稱和密碼,或提示使用 portlet 中儲存的使用者名稱和密碼。

Document Management portlet 在 portlet 的憑證保險庫(Credential Vault)中儲存憑證(credential)—— 如使用者名稱和密碼。憑證是由 portlet 中的每位使用者維護的,必須與使用者登錄檔同步。這就向使用者隱藏了 DB2 Content Manager 的一些與登入有關的複雜問題。

然而,該方法也有一些缺點。首先,它需要為使用者提供使用者介面,以維護其 DB2 Content Manager 憑證。其次,在 portlet 和 DB2 Content Manager 伺服器共享同一使用者登錄檔伺服器時,讓使用者手工控制憑證與使用者登錄檔之間的同步也不是很方便。最後,它將憑證暴露為使用者名稱和密碼,這可能引入一些安全缺陷。

為了避免這些缺陷,您可以使用下面將要討論的輕量級第三方認證(Light-weight Third Party Authentication,LTPA)令牌方法來提供單點登入功能。

LTPA 令牌

可以使用 LTPA 令牌在伺服器之間提供單點登入功能。在將 Lotus Workplace 伺服器所在的 WebSphere Application 伺服器配置為使用 LTPA 令牌進行單點登入時,LTPA 令牌(是一個 cookie)將包含已驗證使用者的憑證。

除了使用使用者名稱和密碼連線 DB2 Content Manager 伺服器的 Java API 之外,DB2 Information Integrator for Content Java API 還提供了非可視(non-visual)的 bean,可以使用 LTPA 令牌作為身份驗證的憑證來連線 DB2 Content Manager 伺服器。非可視的 bean 不需要使用者手工維護其憑證,也不需要將憑證暴露為使用者名稱和密碼。但它需要 Lotus Workplace 和 DB2 Content Manager 都接受 LTPA 令牌,以便進行單點登入。

配置 Lotus Workplace 和 DB2 Content Manager

Lotus Workplace 2.0.1

正如上面所提到的,Lotus Workplace 伺服器是執行在 WebSphere Portal 伺服器之上,而 WebSphere Portal 伺服器是執行在 WebSphere Application 伺服器上。為了給 Lotus Workplace 伺服器配置單點登入,需要啟用 WebSphere Application 伺服器的單點登入。關於詳細的指令,請參閱 Lotus Workplace Information Center 中的小節“Configuring Lotus Workplace products for seamless authentication”(請參閱 參考資料)。

DB2 Content Manager 8.2

為了與使用單點登入功能的 Lotus Workplace 進行整合,需要使用 Content Manager System Administration Client 在 DB2 Content Manager 伺服器中執行下列配置:

  • 啟用 Content Manager 伺服器中的單點登入功能。
  • 建立新的許可權集,其中包含 AllowConnectToLogonAllowTrustedLogon 許可權,以及其他任何必要許可權(例如,ClientPrint)。
    提示:為了基於現有的許可權集建立一個新的許可權集,可以右擊現有許可權集,然後選擇 Copy。這將開啟一個新視窗,您可以在該視窗中通過新增新許可權並同時保留現有許可權來建立一個新的許可權集。
  • 將新建立的許可權集分配給需要通過單點登入功能登入到 Content Manager 伺服器的使用者帳號。

使用 eClient 來驗證單點登入功能是否起作用。關於詳細的指令,請參閱 eClient101 Customization and Integration 紅皮書中的小節“17.4 Configuring Content Manager V8.2 for SSO”(請參閱 參考資料)。

開發使用 LTPA 令牌的單點登入 portlet

這一節將闡述如何為 DB2 Content Manager 開發使用 LTPA 令牌的單點登入 portlet。第一步是一步步地建立一個新的單點登入 portlet,而不是直接修改 Document Management portlet。接著,要找出更改 portlet 中的哪些地方的程式碼,這樣,通過使用 LTPA 令牌,這些 portlet 將具有單點登入功能。

建立新的單點登入 portlet

首先,按照下列步驟建立新 portlet 的骨架(skeleton):

  1. 在 WebSphere Studio Application Developer 中,選擇 File > New > Project。然後單擊 Next
  2. 選擇左邊皮膚中的 Portlet Development,然後選擇右邊皮膚中的 Portlet Project。最後單擊 Next
  3. Project name 欄位中輸入 CMSSO,然後選擇 Basic portlet 作為新 portlet 的型別,並選中 Configure advanced options 核取方塊。最後單擊 Next
  4. 在 EAR project 欄位中輸入 CMSSOEAR,為 CMSSO 選擇 Content root,並選擇 J2EE level 1.3\WebSphere Portal 5.0。然後單擊 Finish
  5. 在 Portlet Perspective 檢視中,選擇 Window > Preference
  6. 在左邊皮膚中選擇 Java > Classpath Variable。然後單擊右邊皮膚中的 New
  7. 在 Name 欄位中輸入 CMBROOT。在 Path 欄位中輸入 Content Manager 的安裝路徑(例如:X:\Program Files\IBM\CM82)。然後單擊 OK
  8. 在 Name 欄位中輸入 CMBHOME。在 Path 欄位中輸入 Content Manager 的公共檔案(common files)的目錄名(例如:X:\Program Files\IBM\CMgmt)。然後單擊 OK
  9. 在 Portlet Perspective 檢視中,右擊 CMSSO 專案並選擇 Properties
  10. 單擊 Add Variable。選擇 CMROOT 並單擊 Extend。然後選擇 lib\cmb81.jar 並單擊 OK
  11. 單擊 Add Variable。選擇 CMROOT 並單擊 Extend。然後選擇 lib\cmbsdk81.jar 並單擊 OK
  12. 單擊 Add Variable。然後選擇 CMHOME 並單擊 OK

在以上步驟中,您建立了新的示例 portlet,並向專案類路徑(classpath)新增了一些 Content Manager 的 Java 庫(cmb81.jar 和 cmbsdk81.jar)。現在,就可以匯入示例 Java 程式 TConnect.java 和 TListEntities.java(與 Content Manager 捆綁在一起),來測試該 portlet 的 Content Manager 身份驗證了。TConnect.java 是用來連線 Content Manager 伺服器的實用程式類。TListEntities.java 顯示 Content Manager 伺服器上所定義實體型別的細節。請按照下列步驟將這兩個 Java 檔案與 portlet 進行整合。

  1. 在 Portlet Perspective 檢視中,選擇 CMSSO project > Java Resources > cmsso。然後右擊 cmsso 並選擇 Import。最後找出檔案 TConnect.javaTListEntities.java,並匯入它們。
  2. 在上面的兩個檔案開頭的地方新增 package cmsso,並對它們進行編譯。
  3. CMSSOPortlet.java 檔案中,請按照下列內容修改 actionPerformed() 函式。
    if (FORM_ACTION.equals(actionString)) {
      // Set form. text in the session bean
      sessionBean.setFormText(request.getParameter(TEXT));
      // Replace the parameters with the proper values
      String [] args ={"ICM","ICMNLSDB","icmadmin","password"};
      try {
        TListEntities.main(args);
      } catch (Exception e) {
        e.printStackTrace(System.out);
      }
    }
    System.out.println("

  4. 將專案匯出為 WAR 檔案,並將它部署到 Lotus Workplace 伺服器上。
  5. 將 Content Manger 公共目錄新增到 Portal 類路徑中。從 WebSphere Administrative Console 中選擇 Environment > Shared Libraries,並單擊 WPSLIB。然後向 CLASSPATH 新增 Content Manager 和 Information Integrator for Content 共享的公共檔案(common files)所在的目錄(例如:D:\IBM\Cmgmt),最後單擊 OK
  6. 重啟伺服器,並登入至 Lotus Workplace。載入包含 portlet 的頁面,並單擊 Submit 按鈕,檢視日誌檔案是否輸出了 Content Manager 伺服器上定義的實體型別。

如果該 portlet 正常工作,那麼可以開始修改程式碼來新增 LTPA 令牌驗證了。DB2 Information Integrator for Content Java API 提供了非可視的 bean,即 CMBConnection,您可以用它來連線使用 LTPA 令牌作為驗證憑證的 DB2 Content Manager Server。

CMBConnection 的方法 connectWithCredential() 接受三個引數:伺服器名(server name)、憑證物件(credential object)和連線字串(connect string)。為了在連線 Content Manager 伺服器時啟用 LTPA 令牌作為憑證,需要新增下列程式碼,將 Content Manager 伺服器連線到 TConnect.java:

  /**
   * Connects to a given server using LTPA token.
   * @param connection an instance of CMBConnection bean
   * @param dstype the datastore type.
   * @param server the server name.  A connection string can
   *   also be specified following the name, in parenthesis
   * @param ltpaToken the ltpaToken.
   */
  public static void connect(CMBConnection connection, String dstype, 
                              String server, String ltpaToken)
	throws Exception {
      // If the server name is followed by a parenthesized string,
	// use that string for the connect string.
	if (server.indexOf("(") > 0) {
	  String connectString = server.substring(server.indexOf("(")+1);
	  server = server.substring(0, server.indexOf("("));
	  if (connectString.endsWith(")")) {
	    connectString = connectString.substring(0, 
                              connectString.length() - 1);
	  }
	  connection.setConnectString(connectString);
	  }
        
	// Set properties on connection bean
	connection.setDsType(dstype);
	// Use the connect method to connect.  This will
	// create the correct type of DKDatastore object (see Java API)
	// and call its connect method.
	System.out.println("Connecting to server");
	connection.connectWithCredential(server, ltpaToken, "");
	System.out.println("OK, Connected");
	// Enable display names support. This will cause 
      // CMBSchemaManagement, CMBEntity, CMBAttribute, CMBItem to use 
      // display names when working with CMv8 (default is to use 
      // non-display names).
	connection.setDisplayNamesEnabled(true);
  }

為了使用 TConnect.java 中的新 connect() 方法,還需要修改 TListEntities.java 的 main() 函式。下面是新的 main() 方法的程式碼:

public static void main(String[] args) throws Exception {
  if (args.length < 3) {
    System.out.println(
      "Displays details on types of entities defined on the server. \n"
         + "Syntax: \n"
         + "  java TListEntities    [] \n"
         + "where: \n"
         + "   is the type of server (Fed, ICM, DL, OD, DB2) \n"
          + "   is the name of the server or database.  This can be \n"
          + "           followed by a connect string in parenthesis. \n"
          + "   is the ltpaToken \n"
          + "   optional, the name of a particular entity.  Detailed \n"
          + "           information will be displayed about the entity. \n"
          + "Examples: \n"
          + "  java TListEntities ICM icmnlsdb ltpaToken \n"
          + "  java TListEntities ICM icmnlsdb ltpaToken 'Document (for Document data model)' \n"
          + "  java TListEntities DL libsrvrn ltpaToken \n"
          + "  java TListEntities Fed cmbdb ltpaToken \n"
          + "  java TListEntities DB2 sample ltpaToken emp_photo \n"
          + "  java TListEntities OD odserver ltpaToekn \n"
          + "where single quotes are used around entity and attribute names that contain spaces");
    System.exit(0);
  }
  String dstype = args[0];
  String server = args[1];
  String ltpaToken = args[2];
    
  String entity = null;
  int nextArg = 4;
  if (nextArg < args.length && args[nextArg] != null) {
    if (args[nextArg].startsWith("'"))
    {
      String arg = args[nextArg];
      while (nextArg 

為了呼叫 TListEntities.java 的新 main() 方法,需要修改 CMSSOPortlet.java 的 actionPerformed() 方法。首先,獲取 LTPA 令牌。然後將它傳遞給 main() 函式。LTPA 令牌是一個 cookie,可以從 PortletRequest Java 物件中檢索它。下面是用來檢索 LTPA 令牌和呼叫 TListEntities.main() 的程式碼:

...
Cookie[] cookies = request.getCookies();
String LtpaToken = null;
if (cookies != null && cookies.length > 0) {
  for (int i = 0; i < cookies.length; i++) {
    if (cookies[i].getName().equalsIgnoreCase("LtpaToken")) {
      LtpaToken = cookies[i].getValue();
    }
  }
}
String [] args ={"ICM","ICMNLSDB",""};
args[2] = LtpaToken;
try {
	TListEntities.main(args);
} catch (Exception e) {
	e.printStackTrace(System.out);
}
System.out.println("

現在,您已經完成了單點登入 portlet。您可以構建專案,將該專案匯出為 WAR 檔案,並將它部署到 Lotus Workplace 伺服器上。

用單點登入增強 Document Management portlet

在測試了上面所建立的新單點登入 portlet 之後,就可以開始增強本系列第 5 部分和第 6 部分中開發的 Document Management portlet 了。

新增單點登入功能的過程包含兩個步驟。首先,需要新增一個函式,用該函式來連線使用 LTPA 令牌的 Content Manager 伺服器。其次,需要修改 portlet 中的程式碼,其中使用者和密碼是從憑證保險庫中檢索獲得的,將用於連線 Content Manager 伺服器。

與 TConnect.java 示例相似,Document Management portlet 也有一個實用程式類,其中包含所有的連線和斷開連線的函式。這個類就是 ICMConnectDisconnect。您需要將 TConnect.java 匯入 com.ibm.bsd.util 包,並向 ICMConnectDisconnect.java 檔案新增下列程式碼:

public static DKDatastoreICM connectWithCredential(String 
                userName, String ltpaToken)
  throws DKException, CMBException, Exception {
  // retrieve connection parameters from property file    	
  PropertyResourceBundle bundle =
    (PropertyResourceBundle) PropertyResourceBundle.getBundle(
		BSDConstants.PROPERTY_FILE_NAME);
  String database = 
    bundle.getString(BSDConstants.PROPERTY_DATABASE_NAME);
  CMBConnection connBean = new CMBConnection();
  // you need to set userid for some CM operations to work
  connBean.setUserid(userName);
  System.out.println(
	"Connecting to datastore (Database '"
		+ database
		+ "', LtpaToken '"
		+ ltpaToken
		+ "'");
  //connBean.connect();
	
  TConnect.connect(connBean, "ICM", database, ltpaToken);
  /*
    connBean.setDsType("ICM");
    connBean.connectWithCredential("database", ltpaToken, "");
  */
	
  System.out.println("OK, connected");
  DKDatastoreICM dsICM =
    (com.ibm.mm.sdk.server.DKDatastoreICM)connBean.getDatastore();
	
  System.out.println(
	  "Connected to datastore (Database '"
	    + dsICM.datastoreName()
	    + "', LtpaToken '"
	    + ltpaToken
	    + "').");
  return (dsICM);
}
public static String getLtpaToken(PortletRequest request) {
  Cookie[] cookies = request.getCookies();
  String ltpaToken = null;
  if (cookies != null && cookies.length > 0) {
    for (int i = 0; i < cookies.length; i++) {
	  if (cookies[i].getName().equalsIgnoreCase("LtpaToken")) {
        ltpaToken = cookies[i].getValue();
	  }
    }
  }
  return ltpaToken;
}

為了定位需要進行修改的程式碼,可以搜尋 getPassword4CMFromCredential,並用下列程式碼替換相關的程式碼:

...
//get the portal user id from the portal request object
String userId = request.getUser().getUserID() ;
//extract the password of the portal user from the portal credentials
//String password = 
//PortletCredential4ICMUtil.getPassword4CMFromCredential(request, 
//PortletCredential4ICMUtil.getVault(getPortletConfig().getContext()), 
//userId);
String password = "";
		
//connect using the LTPA token
String ltpaToken = ICMConnectDisconnect.getLtpaToken(request);
DKDatastoreICM store = 
  ICMConnectDisconnect.connectWithCredential(userId, ltpaToken);
// DKDatastoreICM store = 
//   ICMConnectDisconnect.connect(userId,password) ;
sessionBean.setDataStore(store) ;
...

現在,您應該可以使用 Document Management portlet 且無需維護使用者名稱和密碼了。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14751907/viewspace-591931/,如需轉載,請註明出處,否則將追究法律責任。

相關文章