遙測通道 JAAS 配置

配置 JAAS 以鑑別用戶端傳送的 Username

WebSphere MQ 管理者會配置哪些 MQTT 通道需要使用 JAAS 進行用戶端鑑別。 指定要執行 JAAS 鑑別的每個通道的 JAAS 配置名稱。 通道可以全部使用相同的 JAAS 配置,也可以使用不同的 JAAS 配置。 配置定義在 WMQData directory\qmgrs\qMgrName\mqxr\jaas.config中。

jaas.config 檔案依 JAAS 配置名稱組織。 在每一個配置名稱之下,是一份登入配置清單; 請參閱 圖 1

JAAS 提供四個標準「登入」模組。 標準 NT 和 UNIX「登入」模組具有受限制的值。
JndiLoginModule
針對在 JNDI(Java 命名和目錄介面)下配置的目錄服務進行鑑別。
Krb5LoginModule
使用 Kerberos 通訊協定進行鑑別。
NTLoginModule
使用現行使用者的 NT 安全資訊進行鑑別。
UnixLoginModule
使用現行使用者的 UNIX 安全資訊進行鑑別。
使用 NTLoginModuleUnixLoginModule 的問題是遙測 (MQXR) 服務以 mqm 身分執行,而不是以 MQTT 通道身分執行。 mqm 是傳遞至 NTLoginModuleUnixLoginModule 以進行鑑別的身分,而不是用戶端的身分。

若要解決此問題,請撰寫您自己的「登入」模組,或者使用其他標準「登入」模組。 WebSphere MQ Telemetry 隨附了範例 JAASLoginModule.java。 它是 javax.security.auth.spi.LoginModule 介面的實作。 可以使用它來開發您自己的鑑別方法。

您提供的所有新 LoginModule 類別都必須在遙測 (MQXR) 服務的類別路徑上。 請勿將類別放置在類別路徑中的 WebSphere MQ 目錄上。 建立您自己的目錄,並定義遙測 (MQXR) 服務的完整類別路徑。

透過在 service.env 檔案中設定類別路徑,可以擴增遙測 (MQXR) 服務使用的類別路徑。 CLASSPATH 必須大寫,並且類別路徑陳述式只能包含文字。 不能在 CLASSPATH 中使用變數;例如 CLASSPATH=%CLASSPATH% 就是不正確的。 遙測 (MQXR) 服務會設定其專屬類別路徑。 會將定義在 service.env 中的 CLASSPATH 新增至該類別路徑。

遙測 (MQXR) 服務提供兩個回呼,它們會傳回連接至 MQTT 通道的用戶端的 UsernamePasswordUsernamePasswordMqttConnectOptions 物件中設定。 如需如何存取 使用者名稱密碼的範例,請參閱 圖 2

範例

具有一個具名配置 MQXRConfig 的 JAAS 配置檔範例。
圖 1. 範例 jaas.config 檔案
MQXRConfig {
  samples.JAASLoginModule required debug=true;
  //com.ibm.security.auth.module.NTLoginModule required;
  //com.ibm.security.auth.module.Krb5LoginModule required
  //                 principal=principal@your_realm
  //                 useDefaultCcache=TRUE
  //                 renewTGT=true;
  //com.sun.security.auth.module.NTLoginModule required;
  //com.sun.security.auth.module.UnixLoginModule required;
  //com.sun.security.auth.module.Krb5LoginModule required
  //                 useTicketCache="true"
  //                 ticketCache="${user.home}${/}tickets";
};
「JAAS 登入」模組的範例,編寫目的是接收 MQTT 用戶端提供的 UsernamePassword
圖 2. 範例 JAASLoginModule.Login() 方法
  public boolean login()
      throws javax.security.auth.login.LoginException {
    javax.security.auth.callback.Callback[] callbacks = 
      new javax.security.auth.callback.Callback[2];
    callbacks[0] = new javax.security.auth.callback.NameCallback("NameCallback");
    callbacks[1] = new javax.security.auth.callback.PasswordCallback(
        "PasswordCallback", false);
    try {
      callbackHandler.handle(callbacks);
      String username = ((javax.security.auth.callback.NameCallback) callbacks[0])
          .getName();
      char[] password = ((javax.security.auth.callback.PasswordCallback) callbacks[1])
          .getPassword();
      // Accept everything.
      if (true) {
        loggedIn = true;
      } else 
        throw new javax.security.auth.login.FailedLoginException("Login failed");
      
      principal= new JAASPrincipal(username);
      
    } catch (java.io.IOException exception) {
      throw new javax.security.auth.login.LoginException(exception.toString());
    } catch (javax.security.auth.callback.UnsupportedCallbackException exception) {
      throw new javax.security.auth.login.LoginException(exception.toString());
    }
    
    return loggedIn;
  }