2011年7月19日 星期二

Trusted Context in DB2

在過去的3-tier應用程式中,App Server使用一個固定的user name與後端的DB Server建立起連結。這種作法容易造成必需grant給該user name所有的權限,才能讓App Server操作所有的功能,因而無法達到較細緻化的權限控管。然而,App Server若要為每一個應用程式的End User都建立一個connection的化,又太過耗費系統資源。

DB2的Trusted Context即是設計來解決這樣的問題。如下圖(擷自此),只要在DB2 定義一個Context物件,並且在上面設定可以套用該Context的條件(如連線的IP)。當符合這些條件的App Server在建立Connection時,就可以連結到這個Context物件。一但與這個Context物件連結,App Server可以動態更換End User的ID,而不需重新建立Connection。如此一來,就可以讓同一個Connection給不同的End User使用。

Three-tier application model with trusted context

以下為建立Trusted Context之語法(詳細語法介紹可參照參考資料2)

CREATE TRUSTED CONTEXT contextName BASED UPON CONNECTION USING
SYSTEM AUTHID root_authorization_name
ATTRIBUTES (ADDRESS 'ip_addr', ENCRYPTION 'NONE')
WITH USER FOR other_user_authorization_name with authentication

其中,root_authorization_name為此Trusted Context所連結的使用者ID,只有這個使用者才能從App Server建立Trusted Connection;另other_user_authorization_name則是App Server在換end user  ID時,可以更換的user id。

建立好之後,可以用下列sample code來進行測試

public class TestDB2TrustedContext {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        DB2ConnectionPoolDataSource dataSource = new DB2ConnectionPoolDataSource();
        dataSource.setDatabaseName("PULI");
        dataSource.setServerName("localhost");
        dataSource.setPortNumber(50000);
        dataSource.setDriverType(4);
        Properties properties = new Properties();
        String user = "rootUser";
        String password = "rootPassword";
        try {
            /*傳回的 objects[0]為DB2PooledConnection
             *      objects[1]為之後要更改user name時,所要給的cookie
             */
           Object[] objects = dataSource.getDB2TrustedPooledConnection(
                    user,password, properties);
            DB2PooledConnection pooledConn = (DB2PooledConnection) objects[0];
            Connection conn = pooledConn.getConnection();
            PreparedStatement stmt = conn.prepareStatement("Select name from db2admin.basicinfo fetch first 10 rows only");;
            ResultSet result = stmt.executeQuery();
            while (result.next()){
                System.out.println(result.getString(1));
                Thread.sleep(500);
            }
            byte[] cookie = (byte[])objects[1];
            String newUser="otherUser";
            String newPwd = "otherPasswd";
            /*Mainframe才要用的*/
            String userRegistry = "registry";
            /*先不要給Security Token*/
            byte[] userSecTkn = null;
            /*先前的使用者ID,可不給*/
            String originalUser = null;
            /*重用舊的connection,並重新設定使用者名稱*/
           conn =
                  ((com.ibm.db2.jcc.DB2PooledConnection)pooledConn).getDB2Connection(
                     cookie,newUser,newPwd,userRegistry,userSecTkn,originalUser,properties);
            PreparedStatement stmt2 = conn.prepareStatement("Select name from db2admin.basicinfo fetch first 10 rows only");;
            ResultSet result2 = stmt2.executeQuery();
            while (result2.next()){
                System.out.println(result2.getString(1));
                Thread.sleep(500);
            }      
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

參考資料

  1. http://www.ibm.com/developerworks/data/library/techarticle/dm-0609mohan/
  2. Create Trusted Context語法