概述
在以前文章 如何在阿里雲上安全的存放您的配置 - 續 中,咱們講述了雲上安全存放配置的方法。基於前文原理,本文將以代碼示例方式講解如何基於配置中心產品 ACM 將應用配置(如 數據庫鏈接配置)從應用程序代碼中解耦,從而達到如下目的:html
- 安全合規:應用程序和生產環境上將不須要發佈和持久化任何程序敏感信息;
- 敏捷發佈:數據庫鏈接串配置修改動態生效,不須要程序從新發布甚至重啓;
示例程序架構和準備工做
文章中的示例將分爲如下幾個步驟:java
- 配置 ACM 和 RAM,設置 ECS RAM Role,並進行 ACM 受權,來受權 ECS 上的應用免 AK/SK(即 AccessKey/SecretKey) 來調用 ACM;
-
讀取配置程序編寫:使用 ACM Java SDK 動態讀取配置內容,來進行數據庫配置。mysql
-
其中,程序中不含任何敏感配置,如數據庫鏈接串,阿里雲 AK/SK等;sql
- 數據庫鏈接串在 ACM 上動態刷新,應用不停機。
-
程序代碼架構以下圖所示:數據庫
開始前,用戶應準備好:安全
- 在阿里雲上購買 ECS;
- 在阿里雲上開通 ACM, RAM 等免費服務產品;
- 準備好數據庫,可在阿里雲上開通數據庫或在 ECS 上自行搭建,數據庫裏面可準備好一張 user 表,並準備若干記錄;
- 準備好可訪問數據庫的 Java 應用程序 (或從這裏下載完整代碼示例下載)。
配置ACM和RAM
該章節分爲兩個部分:架構
- 在 ACM 中配置相關敏感信息;
- 經過 RAM 設置用戶的 ECS 的 RAM Role;
在 ACM 控制檯中建立配置
代碼示例所需數據庫鏈接的配置運維
- Data ID:
com.alibaba.cloud.acm:jdbc-sample.properties - Group:非必選,在「更多高級選項」中,默認值爲「DEFAULT_GROUP」
DEFAULT_GROUP - 配置內容, 可根據實際狀況進行配置:
jdbc.url=xxx
jdbc.username=xxx
jdbc.password=xxxide
配置 ECS RAM Role
在ACM程序訪問中,用戶可設置 AccessKey、SecretKey 屬性的方式來訪問 ACM 產品,可是在本文中推薦經過「ECS 實例角色」的方式來訪問ACM。該方式自動獲取臨時憑證,提升安全性和下降運維成本,憑證週期由 ACM SDK 自動維護,應用運行時只需設置 JVM 參數「-Dram.role.name=ramRoleName」,ramRoleName」,ramRoleName 爲授予該 ECS 的 RAM 角色名稱,如 ECS-RAM。運行命令以下:函數
java -jar -Dram.role.name=ECS-RAM sample-1.0-SNAPSHOT-jar-with-dependencies.jar
關於如何設置 ECS 實例角色,請參考「ECS 實例角色」文章。爲減小文章篇幅,本文不贅述了。
讀取配置程序編寫
該章節分爲三個部分:
- 在 ACM 中初始化 ACM 鏈接,用戶僅需填寫配置信息,無需填寫 AK/SK 敏感信息;
- 讀取 ACM 配置,並監聽配置變化;
- 相關業務代碼編寫,根據需求創建數據庫鏈接並查詢數據;
在程序中初始化 ACM,並讀取相關配置
- namespace:命名空間 ID,在控制檯「命名空間詳情」的「命名空間ID」處能夠獲取到
- endpoint: ACM 鏈接域,在控制檯「命名空間詳情」的「End Point」處能夠獲取到
private void initACM() { Properties properties = new Properties(); String namespace = "1ca01ca0-11b0-1e01-0df1-d1010101bc10"; String endpoint = "acm.aliyun.com"; properties.put("endpoint", endpoint); properties.put("namespace", namespace); ConfigService.init(properties); }
經過 ACM 獲取配置並監聽配置變化
獲取數據庫鏈接配置的內容,而且添加配置監聽器。當數據庫鏈接配置的內容須要變動,在 ACM 控制檯修改後,程序實時接收到新的內容,新的數據庫鏈接也實時生效,不中斷程序的運行。
- dataId:剛剛新建配置時 Data ID 所填寫的值
- group:剛剛新建配置時 Group 所填寫的值,默認爲「DEFAULT_GROUP」,隱藏在「更多高級選項」中
private void initJDBCProperties() throws ConfigException { String dataId = "com.alibaba.cloud.acm:jdbc-sample.properties"; String group = "DEFAULT_GROUP"; properties = ConfigService.getConfig2Properties(dataId, group, 3000); // 添加配置監聽 ConfigService.addListener(dataId, group, new ConfigChangeListener() { @Override public void receiveConfigInfo(String content) { Properties properties = new Properties(); try { properties.load(new StringReader(content)); } catch (IOException e) { LOGGER.error("addListener", e); } SampleApp.this.properties = properties; } }); }
創建數據庫鏈接並查詢數據
從 ACM 獲取到的鏈接數據庫所需的地址、用戶名、密碼,經過 MySQL JDBC 驅動包「mysql-connector-java」與 MySQL 服務創建鏈接。接着,再查詢「user」表的總記錄數,返回給函數調用者。
注: 程序中使用的鏈接信息爲ACM中保存的最新的數據庫鏈接信息,鏈接信息經過上面的ACM的監聽配置程序進行動態刷新,從而保證爲最新。
private int count() { String url = properties.getProperty("jdbc.url"); String username = properties.getProperty("jdbc.username"); String password = properties.getProperty("jdbc.password"); Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = DriverManager.getConnection(url, username, password); statement = connection.createStatement(); resultSet = statement.executeQuery("select count(*) from `user`"); if (resultSet.next()) { return resultSet.getInt(1); } } catch (SQLException e) { LOGGER.error("count", e); } finally { close(connection, statement, resultSet); } return 0; }
測試運行
若是你按照本片文章前面工做,完成了 ECS RAM Role 設置和受權之後,可在不設置任何 AK/SK 狀況下,將程序實例打包成可執行 jar 後,上傳到對應的 ECS 環境上運行便可。當程序運行時,如 如何在阿里雲上安全的存放您的配置 - 續 文章所描述的,程序將自動獲取臨時憑證訪問 ACM,憑證週期由 ACM SDK 自動維護。應用運行時只需設置 JVM 參數「-Dram.role.name=ramRoleName」,ramRoleName」,ramRoleName 爲授予該 ECS 的 RAM 角色名稱,如 ECS-RAM。運行命令以下:
java -jar -Dram.role.name=ECS-RAM sample-1.0-SNAPSHOT-jar-with-dependencies.jar
本代碼示例經過 ACM 控制檯配置 JDBC 的鏈接屬性,再使用 ACM Java SDK 讀取配置內容,與 MySQL 創建鏈接,查詢「用戶」數據,最後將結果打印出來,控制檯輸出內容以下:
總記錄數: 9
注:若是是在您本身電腦上或本地測試,須要手動設置 AccessKey、SecretKey 屬性,才能夠訪問 ACM 產品,目前支持三種設置方式,本示例可以使用環境變量,以下:
spas_accessKey=xxx spas_secretKey=xxx