Derby數據庫學習2:安全配置
不安全的數據庫會受到多種安全威脅,包括:
(1)網絡JDBC:來自網絡的JDBC連接會將數據庫服務器本身暴露給本來無權操作數據庫的用戶。
(2)明文數據:網絡數據在默認條件下以明文傳輸。
(3)資源占用:默認情況下數據庫操作會占用無限的內存、CPU資源。
(4)訪問控制:默認情況下Derby的用戶擁有對任意數據庫的任意訪問權限。
對于網絡環(huán)境下的Derby數據庫,一個數據庫管理員需要完成以下安全配置:
(1)操作系統(tǒng)級別安全配置。
(2)為derby.properties和Derby數據庫配置操作系統(tǒng)用戶訪問權限。
(3)為數據庫提供粗粒度(數據庫用戶)和細粒度(不同用戶的權限)的訪問控制。
(4)使用TLS網絡連接加密。
(5)配置JVM安全策略。
2.1 數據庫加密
安全工作的第一步是數據加密。創(chuàng)建數據庫時,可指定啟動密碼和加密方式:
connect 'jdbc: derby: /home/user/school; create = true; dataEncryption = true; encryptionAlgorithm = AES/ OFB/ NoPadding; bootPassword = thisismypassword; ';
連接的時候也要帶上這個bootPassword:
jdbc:derby://127.0.0.1:40000/school;bootPassword=thisismypassword
2.2 TLS配置
安全工作的第二步是TLS加密配置。Derby提供對等加密支持,就是客戶端和服務器端互相驗證身份。首先需要在開發(fā)平臺上創(chuàng)建4個證書庫:
keytool -genkey -alias server -keystore \ /home/user/Notes/jee/db/database/certificates/server.keystore
keytool -genkey -alias client -keystore \ /home/user/Notes/jee/db/database/certificates/client.keystore
keytool -genkey -alias client_saved -keystore \ /home/user/Notes/jee/db/database/certificates/client_saved.keystore
keytool -genkey -alias server_saved -keystore \ /home/user/Notes/jee/db/database/certificates/server_saved.keystore
server.keystore是服務器端私鑰,需在數據庫服務器上妥善保管。client.keystore是客戶端私鑰,每個客戶端可以提供一個。client_saved.keystore保存服務器的證書,位于客戶端,server_saved.keystore位于服務器端,保存客戶端的證書。然后創(chuàng)建服務器端的證書:
keytool -export -alias server -keystore \
/home/user/Notes/jee/db/database/certificates/server.keystore -rfc -file /home/user/Notes/jee/db/database/certificates/server.cert -storepass 123456
考慮到服務器一般只有一個,因此只需生成一個即可。這個證書需要添加到client_saved證書庫中,以便客戶端驗證服務器的身份:
keytool -import -alias server -file \
/home/user/Notes/jee/db/database/certificates/server.cert \
-keystore \
/home/user/Notes/jee/db/database/certificates/client_saved.keystore \-storepass 123456
同樣,需要創(chuàng)建客戶端證書,注意客戶端證書可以有多個:
keytool -export -alias client -keystore \
/home/user/Notes/jee/db/database/certificates/client.keystore -rfc -file /home/user/Notes/jee/db/database/certificates/client.cert -storepass 123456
所有的客戶端證書都必須添加到server_saved證書庫中:
keytool -import -alias client -file \
/home/user/Notes/jee/db/database/certificates/client.cert \
-keystore /home/user/Notes/jee/db/database/certificates/server_saved.keystore -storepass 123456
在服務器端,需要修改DERBY_OPTS環(huán)境變量以提供SSL支持:
export DERBY_OPTS= \
"-Djavax.net.ssl.keyStore=/home/user/Notes/jee/db/database/certificates/server.keystore\
-Djavax.net.ssl.keyStorePassword=123456 \
-Djavax.net.ssl.trustStore=/home/user/Notes/jee/db/database/certificates/ server_saved.keystore
-Djavax.net.ssl.trustStorePassword=123456"
相應的,客戶端ij也要修改DERBY_OPTS:
export DERBY_OPTS= \
"-Djavax.net.ssl.trustStore=/home/user/Notes/jee/db/database/certificates/client_saved.keystore \
-Djavax.net.ssl.trustStorePassword=123456 \
-Djavax.net.ssl.keyStore=/home/user/Notes/jee/db/database/certificates/client.keystore \
-Djavax.net.ssl.keyStorePassword=123456"
對于自行編寫的客戶端程序,則需要調用java.lang.System.setProperty:
java.lang.System.setProperty("javax.net.ssl.trustStore", \
"/home/user/Notes/jee/db/database/certificates/client_saved.keystore")
java.lang.System.setProperty("javax.net.ssl.trustStorePassword", "123456") \
java.lang.System.setProperty("javax.net.ssl.keyStore",\
"/home/user/Notes/jee/db/database/certificates/client.keystore")
java.lang.System.setProperty("javax.net.ssl.keyStorePassword", "123456")
java.lang.Class.forName("org.apache.derby.jdbc.ClientDriver")
conn = java.sql.DriverManager.getConnection("jdbc:derby://127.0.0.1:40000/school;\ bootPassword=thisismypassword;ssl=peerAuthentication;")
2.3 用戶驗證
安全工作的第三步是提供用戶驗證機制。事實上,Derby的用戶驗證可以選擇LDAP,但由于每一次創(chuàng)建連接時都需要查詢LDAP服務器,且Derby并不支持LDAP組,因此并不實用,在這里僅記錄內置在數據庫中的NATIVE驗證機制。創(chuàng)建數據庫時,可以在ij中指定一個用戶:
connect 'jdbc:derby:/path_to_db;create=true;user=me;';
注意沒有密碼。用戶me(當然也可以是別的名稱)就是數據庫的管理員,(應當)擁有一切權限。但是me用戶目前還沒有密碼,調用數據庫函數添加用戶及密碼。注意第一個用戶必須是me:
call SYSCS_UTIL.SYSCS_CREATE_USER('me', 'password');
還可以繼續(xù)添加其他用戶,這些用戶都是具有一切權限的。退出數據庫:
connect 'jdbc:derby:/path_to_db;shutdown=true;';
再次登陸,就必須要求輸入密碼了:
connect 'jdbc:derby:/path_to_db;user=me;password=password;';
假如不輸入,會返回錯誤:
錯誤08004:發(fā)生連接驗證失敗。原因:驗證無效。
2.4 用戶權限管理
安全工作的第四步是用戶權限管理。用戶權限管理分為兩個層面:
(1)粗粒度:用戶被分為兩組,即讀寫權限用戶和只讀權限用戶。
(2)細粒度:為不同的數據庫對象指定可用用戶。
2.4.1 粗粒度管理
首先創(chuàng)建用戶,然后以管理員賬戶執(zhí)行:
call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.propertiesOnly', 'true');
這一步的目的是禁止外部設置property覆蓋數據庫設置。然后禁止未顯式配置的用戶使用數據庫:
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(
'derby.database.defaultConnectionMode',
'noAccess')
然后配置讀寫權限用戶,注意必須包含自己:
call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.fullAccessUsers', 'me,user1,user2,user3');
然后配置只讀權限用戶。注意,只讀權限用戶在一開始是沒有權限讀取任何表的,只能在細粒度管理中進行進一步配置:
call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.readOnlyAccessUsers', 'common,user4,user5,user6');
2.4.2 細粒度管理
所有用戶創(chuàng)建的數據庫對象都以自己的名字作為前綴,比如me用戶創(chuàng)建的students表全名就是
me.students
如果需要其它只讀權限的用戶(如common)進行訪問,可以使用grant語句:
grant select on students to common;
視圖和觸發(fā)器語法一致。如果撤銷權限,使用revoke語句:
revoke select on students from common;
可以grant和revoke的權限包括:
? DELETE
? EXECUTE
? INSERT
? SELECT
? REFERENCES
? TRIGGER