[英]Scala: How can I establish secure connection to PostgreSQL server?
我想使用基於JDBC的庫以編程方式在Scala中安全地連接到我的PostgreSQL服務器。 此外,我想以openssl
生成的格式存儲所有SSL證書和密鑰文件( 即 , 不是由本機Java庫生成的KeyStore
格式)。
我怎樣才能做到這一點?
我在用:
擴展作為PostgreSQL JDBC驅動程序一部分的org.postgresql.ssl.WrappedFactory
類,然后將擴展類的名稱作為參數傳遞給setSslfactory()
的相應子類的setSslfactory setSslfactory()
方法。
假設您使用自簽名證書作為PostgreSQL服務器的證書( 注意 ,服務器的證書位於文件中,其名稱被指定為配置參數ssl_cert_file
的值),並且
假設您將用於建立連接的PostgreSQL 登錄角色名為database_user
:
使用PostgreSQL服務器的證書簽署具有公用名( CN
)屬性database_user
的客戶端證書。 然后,使用客戶端計算機上的openssl
PEM格式的服務器證書,客戶端證書和客戶端私鑰,以下內容將啟用到PostgreSQL服務器的安全,雙向身份驗證連接:
package mypackage
import org.postgresql.ssl.WrappedFactory
import org.bouncycastle.util.io.pem.PemReader
import java.io.{FileInputStream,FileReader}
import javax.net.ssl.{SSLContext,KeyManagerFactory,TrustManagerFactory}
import java.security.{KeyStore,KeyFactory,SecureRandom}
import java.security.cert.CertificateFactory
import java.security.spec.PKCS8EncodedKeySpec
object SocketFactory {
final val PRIVATE_KEY_FILENAME = "private.key"
final val CLIENT_CERT_FILENAME = "client.crt"
final val SERVER_CERT_FILENAME = "/home/me/.ssl/postgres_server.crt"
def certFromFile(fileName: String) =
CertificateFactory getInstance "X.509" generateCertificate {
new FileInputStream(fileName)
}
}
class SocketFactory extends WrappedFactory {
import SocketFactory._
val sslContext = SSLContext getInstance "TLS"
sslContext init (
{ // key managers: Array[KeyManager]
val kmf = KeyManagerFactory getInstance "SunX509"
kmf init ({
val keyStore = KeyStore getInstance KeyStore.getDefaultType
keyStore load (null, null)
keyStore setKeyEntry ( "",
KeyFactory getInstance "RSA" generatePrivate (
new PKCS8EncodedKeySpec (
new PemReader (
new FileReader(PRIVATE_KEY_FILENAME)
).readPemObject.getContent
)
),
Array[Char](), // no password for this entry
Array(certFromFile(CLIENT_CERT_FILENAME))
)
keyStore
}, Array[Char]())
kmf.getKeyManagers
},
{ // trust managers: Array[TrustManager]
val tmf = TrustManagerFactory getInstance "PKIX"
tmf init {
val keyStore = KeyStore getInstance KeyStore.getDefaultType
keyStore load (null, null)
keyStore setCertificateEntry ("", certFromFile(SERVER_CERT_FILENAME))
keyStore
}
tmf.getTrustManagers
},
SecureRandom getInstance "SHA1PRNG"
)
_factory = sslContext.getSocketFactory
}
使用上述內容,您可以獲得如下所示的Java DataSource
:
def dataSource = {
val ds = new PGSimpleDataSource
ds.setDatabaseName("my_database")
ds.setServerName("myHost.com")
ds.setUser("database_user")
ds.setSsl(true)
ds.setSslfactory("mypackage.SocketFactory")
ds
}
null
作為有意義的參數。 如果您注意到奇怪的行為,請確保您不會在某處意外地傳遞null
方法參數。 openssl
可以使用橢圓曲線加密。 要實現前向保密 ,請考慮在PostgreSQL配置中指定適當的密碼套件, 例如 :
ssl_ciphers = 'DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA'
上面的示例在build.sbt
文件中使用以下庫依賴build.sbt
:
libraryDependencies ++= Seq(
"org.bouncycastle" % "bcpkix-jdk15on" % "1.50",
"org.postgresql" % "postgresql" % "9.3-1100-jdbc4"
)
您的pg_hba.conf
文件需要一個適當的條目,如:
hostssl my_database database_user <client.ip.number>/32 trust clientcert=1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.