Derby数据库学习2:安全配置
不安全的数据库会受到多种安全威胁,包括:
(1)网络JDBC:来自网络的JDBC连接会将数据库服务器本身暴露给本来无权操作数据库的用户。
(2)明文数据:网络数据在默认条件下以明文传输。
(3)资源占用:默认情况下数据库操作会占用无限的内存、CPU资源。
(4)访问控制:默认情况下Derby的用户拥有对任意数据库的任意访问权限。
对于网络环境下的Derby数据库,一个数据库管理员需要完成以下安全配置:
(1)操作系统级别安全配置。
(2)为derby.properties和Derby数据库配置操作系统用户访问权限。
(3)为数据库提供粗粒度(数据库用户)和细粒度(不同用户的权限)的访问控制。
(4)使用TLS网络连接加密。
(5)配置JVM安全策略。
2.1 数据库加密
安全工作的第一步是数据加密。创建数据库时,可指定启动密码和加密方式:
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提供对等加密支持,就是客户端和服务器端互相验证身份。首先需要在开发平台上创建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位于服务器端,保存客户端的证书。然后创建服务器端的证书:
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
同样,需要创建客户端证书,注意客户端证书可以有多个:
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环境变量以提供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,但由于每一次创建连接时都需要查询LDAP服务器,且Derby并不支持LDAP组,因此并不实用,在这里仅记录内置在数据库中的NATIVE验证机制。创建数据库时,可以在ij中指定一个用户:
connect 'jdbc:derby:/path_to_db;create=true;user=me;';
注意没有密码。用户me(当然也可以是别的名称)就是数据库的管理员,(应当)拥有一切权限。但是me用户目前还没有密码,调用数据库函数添加用户及密码。注意第一个用户必须是me:
call SYSCS_UTIL.SYSCS_CREATE_USER('me', 'password');
还可以继续添加其他用户,这些用户都是具有一切权限的。退出数据库:
connect 'jdbc:derby:/path_to_db;shutdown=true;';
再次登陆,就必须要求输入密码了:
connect 'jdbc:derby:/path_to_db;user=me;password=password;';
假如不输入,会返回错误:
错误08004:发生连接验证失败。原因:验证无效。
2.4 用户权限管理
安全工作的第四步是用户权限管理。用户权限管理分为两个层面:
(1)粗粒度:用户被分为两组,即读写权限用户和只读权限用户。
(2)细粒度:为不同的数据库对象指定可用用户。
2.4.1 粗粒度管理
首先创建用户,然后以管理员账户执行:
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 细粒度管理
所有用户创建的数据库对象都以自己的名字作为前缀,比如me用户创建的students表全名就是
me.students
如果需要其它只读权限的用户(如common)进行访问,可以使用grant语句:
grant select on students to common;
视图和触发器语法一致。如果撤销权限,使用revoke语句:
revoke select on students from common;
可以grant和revoke的权限包括:
• DELETE
• EXECUTE
• INSERT
• SELECT
• REFERENCES
• TRIGGER