Ottenere un DataSource
attuazione
Di solito il tuo driver JDBC
fornisce un'implementazione di javax.sql.DataSource
.
Per maggiori dettagli, vedere la mia risposta a una domanda simile.
PGSimpleDataSource
Se si utilizza il driver JDBC da jdbc.postgresql.org
, puoi utilizzare org.postgresql.ds.PGSimpleDataSource
class come il tuo DataSource
attuazione.
Istanziare un oggetto di tipo PGSimpleDataSource
, quindi chiama i metodi setter per fornire tutte le informazioni necessarie per connettersi al server del database. La pagina Web sul sito DigitalOcean elenca tutte queste informazioni per la tua particolare istanza di database.
Fondamentalmente questo:
PGSimpleDataSource dataSource = new PGSimpleDataSource();
dataSource.setServerName( "your-server-address-goes-here" );
dataSource.setPortNumber( your-port-number-goes-here );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );
Nomi server multipli e numeri di porta
Sfortunatamente, la versione singolare dei metodi setServerName
e setPortNumber
sono deprecati. Anche se fastidioso, dovremmo probabilmente usare la versione plurale di quei metodi (setServerNames
&setPortNumbers
) che ciascuno accetta un array. Popoliamo una coppia di array a elemento singolo, String[]
e int[]
, con l'indirizzo del nostro server e numero di porta
usando i valori letterali dell'array:
- { "il tuo-indirizzo-server-va-qui" }
- { il tuo-numero-porta-va-qui }
PGSimpleDataSource dataSource = new PGSimpleDataSource();
String[] serverAddresses = { "your-server-address-goes-here" };
dataSource.setServerNames( serverAddresses );
int[] serverPortNumbers = { your-port-number-goes-here };
dataSource.setPortNumbers( serverPortNumbers );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );
Crittografia SSL/TLS
Infine dobbiamo aggiungere le informazioni per la crittografia SSL/TLS affrontata nella domanda.
Ironia della sorte, non chiama setSsl( true )
Penseresti che chiameremmo setSsl
metodo e passare true
. Ma no. Sebbene sia controintuitivo, impostarlo su true causerà il fallimento dei tentativi di connessione. Non so perché è così. Ma tentativi ed errori mi hanno portato a evitare quella chiamata.
Certificato CA
Affinché l'app Java lato client possa avviare la connessione SSL/TLS, il driver JDBC deve avere accesso al certificato CA utilizzato da Digital Ocean. Nella pagina di amministrazione di Digital Ocean, fai clic su Download CA certificate
link per scaricare un piccolo file di testo. Quel file si chiamerà ca-certificate.crt
.
Dobbiamo inviare il testo di quel file al nostro driver JDBC come una stringa. Procedi come segue per caricare il file in una stringa di testo.
// Get CA certificate used in TLS connections.
Path path = Paths.get( "/Users/basilbourque/Downloads/ca-certificate.crt" );
String cert = null;
try
{
cert = Files.readString( path , StandardCharsets.UTF_8 );
System.out.println( "cert = " + cert );
}
catch ( IOException ex )
{
throw new IllegalStateException( "Unable to load the TLS certificate needed to make database connections." );
}
Objects.requireNonNull( cert );
if ( cert.isEmpty() ) {throw new IllegalStateException( "Failed to load TLS cert." ); }
Passa il testo del certificato CA al tuo driver JDBC con una chiamata a DataSource::setSslCert
. Nota che non lo siamo chiamando setSslRootCert
. Non confondere i due metodi con nomi simili.
dataSource.setSslCert( cert );
Test della connessione
Infine, possiamo utilizzare il DataSource
configurato oggetto per stabilire una connessione al database. Quel codice sarà simile a questo:
// Test connection
try (
Connection conn = dataSource.getConnection() ;
// …
)
{
System.out.println( "DEBUG - Postgres connection made. " + Instant.now() );
// …
}
catch ( SQLException e )
{
e.printStackTrace();
}
Codice esempio completo
Mettendo tutto insieme, vedi qualcosa del genere.
// Get CA certificate used in TLS connections.
Path path = Paths.get( "/Users/basilbourque/Downloads/ca-certificate.crt" );
String cert = null;
try
{
cert = Files.readString( path , StandardCharsets.UTF_8 );
System.out.println( "cert = " + cert );
}
catch ( IOException ex )
{
throw new IllegalStateException( "Unable to load the TLS certificate needed to make database connections." );
}
Objects.requireNonNull( cert );
if ( cert.isEmpty() ) {throw new IllegalStateException( "Failed to load TLS cert." ); }
// PGSimpleDataSource configuration
PGSimpleDataSource dataSource = new PGSimpleDataSource();
String[] serverAddresses = { "your-server-address-goes-here" };
dataSource.setServerNames( serverAddresses );
int[] serverPortNumbers = { your-port-number-goes-here };
dataSource.setPortNumbers( serverPortNumbers );
dataSource.setSslCert( cert );
dataSource.setDatabaseName( "defaultdb" );
dataSource.setUser( "doadmin" );
dataSource.setPassword( "your-password-goes-here" );
// Test connection
try (
Connection conn = dataSource.getConnection() ;
// …
)
{
System.out.println( "DEBUG - Postgres connection made. " + Instant.now() );
// …
}
catch ( SQLException e )
{
e.printStackTrace();
}
Fonte attendibile
Quando crei la tua istanza Postgres su DigitalOcean.com, ti verrà offerta la possibilità di limitare le richieste di connessione in entrata. È possibile specificare un singolo indirizzo IP previsto dal server Postgres, una "fonte attendibile" nel gergo di Digital Ocean. Tutti gli hacker che tentano di connettersi al tuo server Postgres verranno ignorati poiché provengono da altri indirizzi IP.
Suggerimento:fare clic all'interno del campo di immissione dati per questo numero di indirizzo IP in modo che la pagina Web rilevi e offra automaticamente l'indirizzo IP attualmente utilizzato dal browser Web. Se stai eseguendo il tuo codice Java dallo stesso computer, utilizza lo stesso numero IP come unica fonte attendibile.
Altrimenti, digita l'indirizzo IP del computer che esegue il codice JDBC Java.
Altri problemi
Non ho affrontato elaborazioni, come protocolli di sicurezza adeguati da utilizzare per gestire il file del certificato CA, o come esternalizzare le informazioni di connessione ottenendo un DataSource
oggetto da un JNDI
server anziché hard-coding
. Ma si spera che gli esempi sopra ti aiutino a iniziare.