在過去的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使用。
以下為建立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();
}
}
}
參考資料