不要讓您的云應用程序數據被破壞
Optim Data Privacy 包含一組數據隱私功能提供程序,它們能夠屏蔽或替換各種信息類型,比如信用卡號、日期和一些國家的全國性 ID。這些數據隱私功能提供程序是跨平臺和跨環境的,被實現為一系列共享庫,而且可由所有支持 C 語言調用約定的應用程序調用。
SQL Database (SQLDB) 在 Bluemix 上提供了 IBM DB2 Enterprise Server Edition 10.5 版的一個基于云的實例,這是 IBM 的開放云架構的一種實現,該實現利用了 Cloud Foundry 使開發人員能夠快速構建、部署和管理云應用程序。因為 SQLDB 屬于 DB2,所以 Optim Data Privacy 特性可以在配備的數據庫實例中提供。
在本教程中您將會看到,Bluemix 和 Optim 提供了必要的工具和技術,幫助您在應用程序中構建有效的數據隱私保護。
您需要滿足的前提條件
要完成本教程的學習,您應該對面向對象的設計和開發具有充分的理解。還應該基本熟悉 JEE Servlet 和關聯的應用編程接口 (API)。因為該應用程序使用了 JDBC 和 SQL,所以了解該 API 和如何編寫 SQL 語句會對您有所幫助。
如果不熟悉 SQLDB,可以在 SQL Database 入門 中了解有關的基本知識。“數據隱私特性” 一節包含一組用戶定義的函數和主要用例。下面將簡短介紹用戶定義的函數和數據隱私特性。
用戶定義的函數
用戶定義的函數 (UDF) 是一種由用戶提供的自定義函數,可像內置函數(比如 ABS、CONCAT 和 SUBSTR)一樣從 SQL 語句調用。Optim Data Privacy UDF 是標量函數,它們接受一個值和一個屏蔽規范字符串作為輸入,返回一個經過屏蔽的值。
標量函數(內置的和 UDF)可用在任何可合法使用列引用或文字的 SQL 語句中。下面這個示例返回一組屏蔽的信用卡號。
單 1. UDF 使用示例
- SELECT
- DB2INST1.OptimMaskStr(CREDITCARD_NUMBER,'pro=ccn,method=repeatable, \
- pattern=6C,wheninvalid=preserve,flddef1=(name=c1,dt=varchar)'),
- FROM USER01.OPTIM_CUSTOMERS
在 Bluemix 中,Optim UDF 安裝在 DB2INST1 SQL Database 目錄中,所以函數名稱必須按上述方式進行限定。所有 Optim UDF 的名稱都以 OptimMask 開頭,以便與其他 UDF 進行區分。函數名稱的后綴表明它接受的數據類型。
在本例中,Str 指一個字符串,比如 CHAR 或 VARCHAR。其他后綴包括 Date(接受一個日期)和 Int16 和 Int32(分別接受 16 和 32 位整數)。
數據隱私特性
Optim Data Privacy 提供程序能夠屏蔽許多不同類型的信息。各種 UDF 可通過屏蔽作為一個輸入參數傳遞的規范字符串,指定要屏蔽的信息類型。
親緣性隱私功能提供程序
可使用親緣性隱私功能提供程序來屏蔽數據,同時保持來源值的格式和字符類型。例如,該提供程序可以保持數據的格式,比如帳號或駕照編號,同時使用字符數據屏蔽字符數據,使用數字屏蔽數字。
年齡隱私功能提供程序
可使用年齡隱私功能提供程序屏蔽一個來源字段中的年齡值。來源值可包含字符、數字、日期或時間戳數據,但必須始終表示一個日期,比如生日。
信用卡隱私功能提供程序
可以使用信用卡隱私功能提供程序來生成一個有效且惟一的信用卡號 (CCN)。在默認情況下,該提供程序使用了一種可重復的方法,通過算法基于來源 CCN 生成一個經過一致地修改的 CCN。在來源數據沒有 CCN 值時,或者不需要以一致的方式轉換來源 CCN 時,該提供程序還可以生成一個隨機值。
電子郵件隱私功能提供程序
可以使用電子郵件隱私功能提供程序生成一個電子郵件地址。電子郵件地址由兩部分組成,一個用戶名和一個域名,它們之間使用 @ 符號分開。例如 user@domain.com。
哈希隱私功能提供程序
可使用哈希隱私功能提供程序,使用一個哈希算法生成的數字值屏蔽來源數據。可以這些數字值為基礎,提供來自查找表或一個值數組的替換數據。
全國性 ID 隱私功能提供程序
可以使用全國性 ID 隱私功能提供程序屏蔽全國性 ID 編號,比如美國社會安全編號。該提供程序可以使用保留了部分來源值的可重復方法,或者使用不會保留來源值的任何部分的隨機方法來屏蔽全國性 ID 編號。該提供程序還包含輸出值的多個分隔符選項(斜杠、句點、空格或無分隔符)。
其他隱私功能提供程序
Optim Data Privacy 提供程序庫還包含用于對通常無法通過算法屏蔽的信息類型(比如姓名和地址)執行查找操作的提供程序。但是,大多數關系數據庫管理系統 (RDMS) 都不允許從 SQL UDF 內訪問數據庫表,所以要執行查找,需要使用哈希隱私功能提供程序,并使用該哈希值作為鍵來選擇查找替換值,比如通過聯結 (join)。
- String vcapServices = System.getenv("VCAP_SERVICES");
- if (vcapServices != null) {
- context.log("Has VCAP_SERVICES.");
- String vcapKey =
- context.getInitParameter(InitParameterNames.VCAP_KEY);
- if (vcapKey != null) {
- context.log("The VCAP key is '" + vcapKey + "'");
- }
- JsonParser parser = new JsonParser();
- try {
- JsonObject services = parser.parse(vcapServices).getAsJsonObject();
- JsonArray array = null;
- JsonObject service = null;
- if (vcapKey != null) {
- context.log("Looking up service '" + vcapKey + "'...");
- JsonElement element = services.get(vcapKey);
- if (element != null) {
- context.log("Service '" + vcapKey + "' found.");
- array = element.getAsJsonArray();
- }
- }
- if (array == null) {
- context.log("Using first available service...");
- Set<Entry<String, JsonElement>> entrySet = services.entrySet();
- Iterator<Entry<String, JsonElement>> iterator =
- entrySet.iterator();
- if (iterator.hasNext()) {
- Entry<String, JsonElement> entry = iterator.next();
- JsonElement element = entry.getValue();
- array = element.getAsJsonArray();
- } else {
- context.log("No services defined.");
- }
- }
- if (array != null) {
- if (array.size() > 0) {
- service = array.get(0).getAsJsonObject();
- String name = service.get("name").getAsString();
- context.log("Service name is '" + name + "'.");
- String label = service.get("label").getAsString();
- context.log("Service label is '" + label + "'.");
- String plan = service.get("plan").getAsString();
- context.log("Service plan is '" + plan + "'.");
- JsonObject credentials =
- service.get("credentials").getAsJsonObject();
- url = credentials.get("jdbcurl").getAsString();
- context.log("URL is '" + url + "'.");
- user = credentials.get("username").getAsString();
- context.log("User is '" + user + "'.");
- password = credentials.get("password").getAsString();
- context.log("Password is '" + password + "'.");
- }
- }
- } catch (Exception e) {
- context.log("Error parsing VCAP_SERVICES", e);
- }
- }
從 VCAP_SERVICES 獲得連接 URL 和憑據后,連接到 SQL Database 就像使用 JDBC 連接到 DB2 LUW 一樣:
清單 3. 連接到 SQL Database
- connection = null;
- ApplicationConfiguration configuration = getConfiguration();
- try {
- connection = DriverManager.getConnection(
- configuration.getUrl(),
- configuration.getUser(),
- configuration.getPassword());
- log("Connected to database.");
- } catch (SQLException e) {
- log("Unable to connect to database.", e);
- }
演示應用程序支持使用清單 6 中所示的 CREATE TABLE AS VIEW 機制來創建一個包含敏感信息的表的副本。像其他 JDBC 應用程序一樣,這些步驟非常簡單:
- 構建要執行的 SQL。
- 從連接中獲取(或重用)一個 SQL 語句。
- 執行該 SQL。
清單 4. 獲取該 SQL 語句
- Connection connection = connectionManager.getConnection();
- if (connection == null) {
- thrownew IllegalStateException("Database connection not available");
- }
- if (connection != this.connection) {
- log("Connection is new or has changed - creating new statement.");
- this.connection = connection;
- if (statement != null) {
- try {
- statement.close();
- } catch (SQLException e) {
- // Ignore.
- }
- }
- statement = connection.createStatement();
- }
- return statement;
清單 5. 執行該 SQL 語句
- Statement statement = getStatement();
- return statement.executeUpdate(sql);
#p#
創建一個屏蔽的表副本涉及兩個步驟:
- 創建新表。
- 插入來自原始表的數據,使用 UDF 屏蔽敏感信息。
清單 6. 創建 SQL 來構建新表
- ApplicationConfiguration configuration = getConfiguration();
- return String.format("CREATE TABLE %s.OPTIM_SALES_MASKED AS
- (SELECT * FROM %s.OPTIM_SALES) WITH NO DATA",
- configuration.getSchema(),
- configuration.getSchema());
清單 7. 創建 SQL 來插入來自原始表的數據
- ApplicationConfiguration configuration = getConfiguration();
- StringBuilder builder = new StringBuilder();
- builder.append(String.format("INSERT INTO %s.OPTIM_SALES_MASKED (\n",
- configuration.getSchema()));
- builder.append(" SALESMAN_ID,\n");
- builder.append(" FIRST_NAME,\n");
- builder.append(" LAST_NAME,\n");
- builder.append(" NATIONALITY,\n");
- builder.append(" NATIONAL_ID,\n");
- builder.append(" PHONE_NUMBER,\n");
- builder.append(" AGE,\n");
- builder.append(" SEX,\n");
- builder.append(" TERRITORY,\n");
- builder.append(" EMAIL_ADDRESS,\n");
- builder.append(" MANAGER_ID\n");
- builder.append(") SELECT SALESMAN_ID,\n");
- builder.append(" FIRST_NAME,\n");
- builder.append(" LAST_NAME,\n");
- builder.append(" NATIONALITY,\n");
- if (configuration.isUseUDFs()) {
- builder.append(" ");
- String udfSchema = configuration.getUdfSchema();
- if (udfSchema != null) {
- builder.append(udfSchema);
- builder.append('.');
- }
- builder.append("OptimMaskStr(NATIONAL_ID,'pro=nid,switch=us,
- wheninvalid=preserve,flddef1=(name=c1,dt=varchar)'),\n");
- } else {
- builder.append(" NATIONAL_ID,\n");
- }
- builder.append(" PHONE_NUMBER,\n");
- builder.append(" AGE,\n");
- builder.append(" SEX,\n");
- builder.append(" TERRITORY,\n");
- builder.append(" EMAIL_ADDRESS,\n");
- builder.append(" MANAGER_ID\n");
- builder.append(String.format(" FROM %s.OPTIM_SALES WHERE NATIONALITY =
- 'U.S.'\n", configuration.getSchema()));
- return builder.toString();
SQL Database DDL
由于 SQL Database 服務作為基于云的產品的性質,該服務提供的 DB2 數據庫存在多種限制和局限性。最明顯的限制是,目前無法從云外部連接到 SQL Database 實例。這使得用戶無法使用 DB2 命令行實用程序和其他 SQL 工具(比如 Eclipse)。但 SQL Database 有一個與 Bluemix 集成的控制臺提供了此功能。
要啟動該控制臺,需要使用您的憑據登錄到 Bluemix。這會調出您的儀表板。在左側,可以訪問應用程序和服務。單擊 SERVICES 展開該列表并選擇您的 SQL Database 服務。
圖 1. 您的 Bluemix 儀表板

1.要啟動該控制臺,需要使用您的憑據登錄到 Bluemix。這會調出您的儀表板。在左側,可以訪問應用程序和服務。單擊 SERVICES 展開該列表并選擇您的 SQL Database 服務。
圖 1. 您的 Bluemix 儀表板

2.這會打開 SQL 控制臺的啟動面板。單擊 LAUNCH,這會在瀏覽器中打開一個新窗口或選項卡。Bluemix 建議采用的默認名稱為 mySQLDB。我選擇使用 sqldb。
圖 2. SQL Database 控制臺啟動面板

3.單擊 Work with Database Objects 查看數據庫實例元數據,比如模式、表、視圖和函數。
圖 3. SQL Database 控制臺

4.如果有多個 SQL Database 服務器綁定到您的應用程序,那么可以使用 Database: 下拉菜單選擇您想要查看和使用的數據庫。
要創建數據庫表和視圖,可以單擊 Run DDL。
圖 4. 使用數據庫對象

#p#
5.這會調出一個選項卡,用于鍵入或粘貼 DDL,或者從您的本地文件系統加載一個 SQL 腳本文件。
圖 5. 運行 DDL

清單 8. DDL 語句
- ------------------------------------------------
- -- DDL Statements for table "USER01 "."OPTIM_CUSTOMERS"
- ------------------------------------------------
- CREATETABLE "USER01 "."OPTIM_CUSTOMERS" (
- "CUST_ID" CHAR(5) NOTNULL ,
- "CUSTNAME" CHAR(20) NOTNULL ,
- "ADDRESS1" VARCHAR(100) NOTNULL ,
- "ADDRESS2" VARCHAR(100) ,
- "LOCALITY" VARCHAR(56) ,
- "CITY" VARCHAR(60) ,
- "STATE" VARCHAR(30) ,
- "COUNTRY_CODE" CHAR(2) ,
- "POSTAL_CODE" VARCHAR(15) ,
- "POSTAL_CODE_PLUS4" CHAR(4) ,
- "EMAIL_ADDRESS" VARCHAR(70) ,
- "PHONE_NUMBER" VARCHAR(20) ,
- "YTD_SALES" DECIMAL(7,2) NOTNULLWITHDEFAULT ,
- "SALESMAN_ID" CHAR(6) ,
- "NATIONALITY" VARCHAR(30) ,
- "NATIONAL_ID" VARCHAR(30) ,
- "CREDITCARD_NUMBER" VARCHAR(19) ,
- "CREDITCARD_TYPE" VARCHAR(30) ,
- "CREDITCARD_EXP" CHAR(4) ,
- "CREDITCARD_CVV" VARCHAR(4) ,
- "DRIVER_LICENSE" VARCHAR(30) ,
- "CREDITCARD_HISTORY" CLOB(1048576) LOGGED NOT COMPACT )
- IN "USERSPACE1" ;
- -- DDL Statements for indexes on Table "USER01 "."OPTIM_CUSTOMERS"
- CREATEUNIQUEINDEX "USER01 "."XPK_CUST" ON "USER01 "."OPTIM_CUSTOMERS"
- ("CUST_ID" ASC)
- COMPRESS NO ALLOW REVERSE SCANS;
- -- DDL Statements for primary key on Table "USER01 "."OPTIM_CUSTOMERS"
- ALTERTABLE "USER01 "."OPTIM_CUSTOMERS"
- ADDPRIMARYKEY
- ("CUST_ID");
- ------------------------------------------------
- -- DDL Statements for table "USER01 "."OPTIM_SALES"
- ------------------------------------------------
- CREATETABLE "USER01 "."OPTIM_SALES" (
- "SALESMAN_ID" CHAR(6) NOTNULL ,
- "FIRST_NAME" VARCHAR(15) NOTNULL ,
- "LAST_NAME" VARCHAR(15) NOTNULL ,
- "NATIONALITY" VARCHAR(30) ,
- "NATIONAL_ID" VARCHAR(30) ,
- "PHONE_NUMBER" VARCHAR(20) NOTNULL ,
- "AGE" SMALLINTNOTNULLWITHDEFAULT ,
- "SEX" CHAR(1) NOTNULLWITHDEFAULT ,
- "TERRITORY" VARCHAR(14) NOTNULL ,
- "EMAIL_ADDRESS" VARCHAR(70) NOTNULL ,
- "MANAGER_ID" VARCHAR(6) )
- IN "USERSPACE1" ;
- -- DDL Statements for indexes on Table "USER01 "."OPTIM_SALES"
- CREATEUNIQUEINDEX "USER01 "."XPK_SALES" ON "USER01 "."OPTIM_SALES"
- ("SALESMAN_ID" ASC)
- COMPRESS NO ALLOW REVERSE SCANS;
- -- DDL Statements for primary key on Table "USER01 "."OPTIM_SALES"
- ALTERTABLE "USER01 "."OPTIM_SALES"
- ADDPRIMARYKEY
- ("SALESMAN_ID");
加載數據
執行必要的 DDL 后,可以將任何所需的數據加載到數據庫實例中。演示應用程序的數據包含兩個表:
- 客戶數據
- 銷售數據
這兩個表包含敏感信息,在真實世界中,應該在用于分析或測試之前先屏蔽這些信息。
圖 6. 客戶數據

圖 7. 銷售數據

以下步驟展示了銷售數據的加載。
1.單擊控制臺的 Getting Started 頁面上的 Load Data,如 圖 3 所示。這會調出 Load Data 頁面。
單擊 Browse files 選擇您的本地文件系統中的一個文件,其中包含逗號分隔值 (CSV) 格式的數據。一定要為 Row one contains the column names 選擇 No。
使用 table 下拉菜單選擇該表,單擊 Load File 將數據上傳到 Bluemix。
圖 8. 瀏覽并上傳數據

上傳并解析文件后,會顯示內容的預覽視圖。單擊 Next 選擇加載目標。
圖 9. 上傳的數據的預覽視圖

確保已選擇 Load into an existing table 并單擊 Next。
圖 10. 選擇目標

#p#
為數據選擇模式 USER01 和目標表。您會看到一個列出了表列的彈出窗口,在確認您已選擇正確的表后,可以關閉此彈窗。
圖 11. 選擇表

如果該表已在上面的 運行 DDL 步驟中創建,那么是附加數據還是替換數據沒有任何區別。如果該表之前已加載,而且您希望重新開始,那么可以選擇 Replace any data in the table with new data,然后單擊 Finish。
Bluemix 將數據加載到表中后,您將獲得一個表明加載、拒絕、刪除和跳過的行數的狀態,以及一個表預覽視圖。
圖 12. 選擇加載選項

加載了客戶和銷售數據后,演示應用程序就可以使用數據庫了。
圖 13. 加載完成

部署和測試您的應用程序
可以使用 Cloud Foundry cf 命令行實用程序 部署 Web 應用程序歸檔文件 (WAR)。
- 在可以部署(推送)應用程序之前,必須登錄到您的 API 端點:
- 可以推送一個
.war文件或一個目錄的內容(布局類似于一個.war文件)。在本例中,只需推送.war文件: - 也可以使用 cf 查詢部署的應用程序和它們使用的服務:
- 完成上述操作后,您應該注銷:
- 應用程序被推送到 Bluemix 后,可以從 Web 瀏覽器通過 http://<app name>.mybluemix.net/ 訪問它。
單擊 Mask Customer Credit Card Numbers 或 Mask Sales Social Security Numbers。
圖 14. 演示應用程序

在下一個屏幕上,單擊 Mask Social Security Numbers。
圖 15. 未屏蔽的銷售數據

預覽將執行的 3 個步驟: 然后單擊 Perform Steps and Compare。
圖 16. 屏蔽銷售錯誤

- 丟棄包含屏蔽的數據的表(如果存在)。
- 創建將包含屏蔽的數據的表。
- 發出一個語句來插入銷售數據,同時屏蔽社會安全編號。
- 檢查屏蔽的數據,您可能注意到,所有社會安全編號都與原始編號不同。
圖 17. 屏蔽的銷售數據

結束語
隨著有關數據隱私的法律法規得到更多的關注,企業擁有具有數據屏蔽功能的應用程序變得至關重要。如本教程所示,IBM Bluemix 和 Optim 提供了必要的技術和工具來幫助您構建這些應用程序。
原文出自:http://www.ibm.com/developerworks/cn/cloud/library/cl-optimprivacy-app/index.html





















