java 06

background image

Java, bazy danych i SSL

1

1. MySQL:

własności połączenia,

transmisja z wykorzystaniem SSL.

2. Własne programy wykorzystujące SSL.

3. RMI i SSL

- implementacja własnych wersji klas

ServerSocket

i

Socket

.

- wykorzystanie własnych gniazd w ramach RMI

- implementacja własnej klasy

RMIClientSocketFactory

.

- implementacja własnej klasy

RMIServerSocketFactory

.

- szyfrowanie SSL w RMI

background image

MySQL i JDBC

Driver JDBC do bazy MySQL:

http://www.mysql.com/products/connector/j/

.

Dokumentacja:

http://dev.mysql.com/doc/refman/5.0/en/java-connector.html

.

Nawiązanie połączenia:

Connection con = DriverManager.getConnection(

"jdbc:mysql://localhost/test?user=monty&password=");

Ogólnie "connectString" ma postać:

jdbc:mysql://[host][,failoverhost...][:port]/[database]
[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...

Domyślny adres host'a to '127.0.0.1'. Domyślny port to '3306'.

jdbc:mysql://[host:port],[host:port].../[database]
[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...

Jeśli nie zostanie podana nazwa bazy danych, w przyszłości należy ją ustawić

metodą

setCatalog()

na rzecz obiektu

Connection

lub w zapytaniach przesyłać

pełne nazwy tabel: (np.

SELECT dbname.tablename.colname FROM

dbname.tablename

).

2

background image

Wybrane własności połączenia

user

– nazwa użytkownika (domyślnie

''

),

password

- hasło (

''

),

useCompression

– czy używać kompresji podczas komunikacji z serwerem

(

false

),

autoReconnect

– czy odtwarzać nieaktywne połączenia (

false

),

useSSL

– czy używać SSL'a podczas komunikacji (

false

),

requireSSL

– wymagać SSL'a gdy

useSSL=true

? (

false

),

logger

– nazwa klasy logującej implementującej

com.mysql.jdbc.log.Log

,

używanej do logowania zdarzeń (

com.mysql.jdbc.log.StandardLogger

),

zeroDateTimeBehavior

– jak obsługiwać daty wypełnione zerami, opcje:

exception

,

round

oraz

convertToNull

(

exception

).

3

background image

Kodowanie znaków

Wszystkie teksty wysyłane przez sterownik do bazy danych są automatycznie

konwertowane z Unikodu (natywne kodowanie w Javie) do kodowania używanego

przez komputer klienta.

Kodowanie znaków między klientem i serwerem jest wykrywane automatycznie

podczas nawiązania połączenia. Kodowanie używane przez sterownik jest ustawiane

po stronie serwera poprzez

character_set

(przed 4.1.0) lub

character_set_server

(od 4.1.0). Aby zmienić automatyczne kodowanie należy

ustawić własność

characterEncoding

w

connectString'u

.

Najczęstsze kodowania nazwa MySQL (nazwa Java):

usa7 (US-ASCII), latin1 (ISO8859_1), latin2 (ISO8859_2), win1250ch (Cp1250),

utf8 (UTF-8), ucs2 (UnicodeBig).

4

background image

Używanie SSL'a

SSL szyfruje wszystkie przesyłane dane. Wydajność komunikacji spada o 35-50%.

Konfiguracja serwera:

http://dev.mysql.com/doc/refman/5.0/en/secure-connections.html.

W skrócie:

konfiguracja kompilacji:

SHOW VARIABLES LIKE 'have_openssl';

wygenerowanie certyfikatów SSL:

http://dev.mysql.com/doc/refman/5.0/en/secure-create-certs.html?ff=nopfpls

zmiany w pliku

my.cnf

,

uruchomienie serwera.

5

background image

Używanie SSL'a

6

1. Import certyfikatu serwera MySQL:

>cp /etc/mysql/openssl/cacert.pem cacert.pem

>keytool -import -alias mysql -file cacert.pem -keystore mysql.store

Enter keystore password:

mysqljava

Owner: CN=Michal Ciesla, O=Internet Widgits Pty Ltd, ST=Some-State, C=pl

Issuer: CN=Michal Ciesla, O=Internet Widgits Pty Ltd, ST=Some-State, C=pl

Serial number: c55bf7ad0557670b

Valid from: Sun Mar 19 20:54:21 CET 2006 until: Tue Apr 18 21:54:21 CEST 2006

Certificate fingerprints:

MD5: FA:3C:B9:34:9E:11:FB:0E:D9:1C:C9:40:A5:3E:CB:E8

SHA1: 4F:9F:A8:C9:B1:3B:8F:CE:0F:7D:B0:CC:C6:E6:5A:53:EA:4B:B7:FC

Trust this certificate? [no]:

yes

Certificate was added to keystore

>

background image

Używanie SSL'a

7

2. Ewentualne wygenerowanie certyfikatu klienta:

>keytool -genkey -keyalg rsa -alias client -keystore
client.store

3. Ustawienie właściwości JVM:

-Djavax.net.ssl.keyStore=/sciezka/do/mysql.store

-Djavax.net.ssl.keyStorePassword=*********

-Djavax.net.ssl.trustStore=/sciezka/do/client.store

-Djavax.net.ssl.trustStorePassword=*********

4. Dodanie do przy połączeniu opcji:

useSSL=true

5. Sprawdzenie – uruchomienie JVM z opcją

-Djavax.net.debug=all

background image

Używanie SSL'a

8

import

java.sql.*;

public

class

MySQLDb {

public

static

void

main(String[] args){

String sString =

"jdbc:mysql://localhost/test?"

+

"user=root&password=haslo&useSSL=true"

;

System.setProperty(

"javax.net.ssl.trustStore"

,

"/path/to/mysql.store"

);

System.setProperty(

"javax.net.debug"

,

"all"

);

try

{

Class.forName(

"com.mysql.jdbc.Driver"

).newInstance();

}

catch

(Exception ex) {

ex.printStackTrace();

return

;

}

try

{

Connection con =

DriverManager.getConnection(sString);

Statement stmt =con.createStatement();

ResultSet rs = stmt.executeQuery(

"SELECT NOW()"

);

rs.next();

System.out.println(rs.getString(1));

con.close();

}

catch

(SQLException ex) { ex.printStackTrace();

}

}

background image

SSL i Java

9

Protokół SSL umożliwia bezpieczną (szyfrowaną) transmisję danych poprzez

niezabezpieczoną sieć. Dodatkowo SSL umożliwia autoryzację stron komunikacji.

W tym celu wykorzystywany jest mechanizm certyfikatów. Za transmisję z użyciem

protokołu SSL odpowiedzialne są klasy zgrupowane w pakiecie

javax.net.SSL

.

Implementacja SSH jest dostępna poprzez zewnętrzne biblioteki. Jedną z nich jest

jsch (http://www.jcraft.com/jsch/).

background image

Przykład: serwer echo

10

import

javax.net.ssl.*;

import

java.io.*;

public

class

EchoServer {

public

static

void

main(String[] args) {

try

{

SSLServerSocketFactory factory = (SSLServerSocketFactory)

SSLServerSocketFactory.getDefault();

SSLServerSocket ss = (SSLServerSocket) factory

.createServerSocket(9999);

SSLSocket s = (SSLSocket) ss.accept();

InputStreamReader isr =

new

InputStreamReader(s.getInputStream());

BufferedReader br =

new

BufferedReader(isr);

String sTmp =

null

;

while

((sTmp = br.readLine()) !=

null

) {

System.

out

.println(sTmp);

System.

out

.flush();

}

}

catch

(Exception ex) {

ex.printStackTrace();

}

}

}

background image

Przykład: klient echo

11

import

javax.net.ssl.*;

import

java.io.*;

public

class

EchoClient {

public

static

void

main(String[] args) {

try

{

SSLSocketFactory factory = (SSLSocketFactory)

SSLSocketFactory.getDefault();

SSLSocket s = (SSLSocket)

factory.createSocket(

"localhost"

, 9999);

InputStreamReader isr =

new

InputStreamReader(System.

in

);

BufferedReader br =

new

BufferedReader(isr);

OutputStreamWriter osw =

new

OutputStreamWriter(s.getOutputStream());

BufferedWriter bw =

new

BufferedWriter(osw);

String sTmp =

null

;

while

((sTmp = br.readLine()) !=

null

) {

bw.write(sTmp +

'\n'

);

bw.flush();

}

}

catch

(Exception ex) {

ex.printStackTrace();

}

}

}

background image

Przykład: uruchomienie programów

12

Pierwsza czynność to wygenerowanie klucza:

keytool -genkey -keystore mySrvKeystore -keyalg RSA

Uruchomienie serwera:

java -Djavax.net.ssl.keyStore=mySrvKeystore
-Djavax.net.ssl.keyStorePassword=123456 EchoServer

Uruchomienie klienta:

java -Djavax.net.ssl.trustStore=mySrvKeystore
-Djavax.net.ssl.trustStorePassword=123456 EchoClient

Dodatkowe parametry wywołania pozwolą zobaczyć informacje związane z
połączeniem SSL:

-Djava.protocol.handler.pkgs=
com.sun.net.ssl.internal.www.protocol
-Djavax.net.debug=ssl

Przykład ze strony: http://tvilda.stilius.net/java/java_ssl.php

background image

SSL i autoryzacja

13

Domyślnie tylko jedna strona komunikacji (serwer) musi potwierdzać swoją

tożsamość. Jeśli konieczne jest potwierdzenie tożsamości klienta należy użyć

metod:

setNeedClientAuth(true)

lub

setWantClientAuth(true)

wywołanych na rzecz obiektu

SSLServerSocket

.

Jeśli chcemy aby żadna ze stron nie musiała potwierdzać swojej tożsamości musimy

zmienić domyślne algorytmy kodowania. Najłatwiej zrobić to tworząc własne

rozszerzenie klasy

SSLSocketFactory

.

Listę obsługiwanych i domyślnych algorytmów uzyskamy za pomocą metod:

getSuppotredCipherSuites()

oraz

getDefaultCipherSuites()

.

background image

SSL i autoryzacja – listy algorytmów

14

Domyślne:

SSL_RSA_WITH_RC4_128_MD5

SSL_RSA_WITH_RC4_128_SHA

TLS_RSA_WITH_AES_128_CBC_SHA

TLS_DHE_RSA_WITH_AES_128_CBC_SHA

TLS_DHE_DSS_WITH_AES_128_CBC_SHA

SSL_RSA_WITH_3DES_EDE_CBC_SHA

SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA

SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA

SSL_RSA_WITH_DES_CBC_SHA

SSL_DHE_RSA_WITH_DES_CBC_SHA

SSL_DHE_DSS_WITH_DES_CBC_SHA

SSL_RSA_EXPORT_WITH_RC4_40_MD5

SSL_RSA_EXPORT_WITH_DES40_CBC_SHA

SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA

SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA

Wspierane: wszystkie domyślne oraz:

SSL_DHE_RSA_WITH_DES_CBC_SHA

SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA

SSL_RSA_WITH_NULL_MD5

SSL_RSA_WITH_NULL_SHA

SSL_DH_anon_WITH_RC4_128_MD5

TLS_DH_anon_WITH_AES_128_CBC_SHA

SSL_DH_anon_WITH_3DES_EDE_CBC_SHA

SSL_DH_anon_WITH_DES_CBC_SHA

SSL_DH_anon_EXPORT_WITH_RC4_40_MD5

SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA

background image

Szyfrowanie w RMI

15

Technologia RMI została zaprojektowana tak, aby można było jej używać z

dowolnymi mechanizmami zapewniającymi transport danych przez sieć,

działającymi ponad protokołem TCP. W praktyce odbywa się to poprzez

implementację własnego obiektu (tzw. socket factory) dostarczającego gniazda

wykorzystywane do komunikacji RMI.

Implementacja własnego socket factory składa się z trzech kroków:

1. Implementacja własnych wersji klas

ServerSocket

i

Socket

.

2. Implementacja własnej klasy

ClientSocketFactory

.

3. Implementacja własnej klasy

ServerSocketFactory

.

background image

1. Implementacja własnych gniazd

16

Przygotujemy gniazda, które będą umożliwiały przesyłanie przez siec danych

kodowanych za pomocą operacji

XOR

i ustalonego, ośmiobitowego wzorca.

XorServerSocket

Socket

XorSocket

ServerSocket

background image

Implementacja XorSocket

17

import

java.io.*;

import

java.net.*;

class

XorSocket

extends

Socket {

private

final

byte

pattern

;

// wzorzec kodowania

private

InputStream

in

=

null

;

private

OutputStream

out

=

null

;

public

XorSocket(

byte

pattern)

throws

IOException {

super

();

this

.

pattern

= pattern;

}

public

XorSocket(String host,

int

port,

byte

pattern)

throws

IOException {

super

(host, port);

this

.

pattern

= pattern;

}

background image

Implementacja XorSocket

18

public

synchronized

InputStream getInputStream()

throws

IOException {

if

(

in

==

null

) {

in

=

new

XorInputStream(

super

.getInputStream(),

pattern

);

}

return

in

;

}

public

synchronized

OutputStream getOutputStream()

throws

IOException {

if

(

out

==

null

) {

out

=

new

XorOutputStream(

super

.getOutputStream(),

pattern

);

}

return

out

;

}

}

background image

Implementacja XorServerSocket

19

import

java.io.*;

import

java.net.*;

class

XorServerSocket

extends

ServerSocket {

private

final

byte

pattern

;

public

XorServerSocket(

int

port,

byte

pattern)

throws

IOException {

super

(port);

this

.

pattern

= pattern;

}

public

Socket accept()

throws

IOException {

Socket s =

new

XorSocket(

pattern

);

this

.implAccept(s);

return

s;

}

}

background image

Implementacja strumieni

20

import

java.io.*;

class

XorOutputStream

extends

FilterOutputStream {

private

final

byte

pattern

;

public

XorOutputStream(OutputStream out,

byte

pattern) {

super

(out);

this

.

pattern

= pattern;

}

public

void

write(

int

b)

throws

IOException {

out

.write((b ^

pattern

) & 0xFF);

}

}

background image

Implementacja strumieni

21

import

java.io.*;

class

XorInputStream

extends

FilterInputStream {

private

final

byte

pattern

;

public

XorInputStream(InputStream in,

byte

pattern) {

super

(in);

this

.

pattern

= pattern;

}

public

int

read()

throws

IOException {

int

b =

in

.read();

if

(b != -1) b = (b ^

pattern

) & 0xFF;

return

b;

}

public

int

read(

byte

b[],

int

off,

int

len)

throws

IOException {

int

n =

in

.read(b, off, len);

if

(n <= 0)

return

n;

for

(

int

i = 0; i < n; i++)

b[off + i] = (

byte

)((b[off + i] ^

pattern

) & 0xFF);

return

n;

}

}

background image

Implementacja socket factories

22

W technologi RMI serwer (zdalny obiekt) decyduje o rodzaju transmisji. Dzięki

temu kod programu klienckiego jest niezależny od zmian (np. szyfrowanie) w

protokole komunikacji. Z drugiej strony wszelkie dane potrzebne do zainicjowania

połączenia są do klienta przesyłane przez sieć – czyli muszą być serializowalne.

Aby utworzyć gniazdo służące do komunikacji RMI korzysta z interfejsów

SocketFactory

oraz

ServerSocketFactory

, które udostępniają odpowiednio

metody

createSocket(String host, int port)

i

createServerSocket(int port)

.

background image

Implementacja

RMIClientSocketFactory

23

import

java.io.*;

import

java.net.*;

import

java.rmi.server.*;

public

class

XorClientSocketFactory

implements

RMIClientSocketFactory,

Serializable

{

private

byte

pattern

;

public

XorClientSocketFactory(

byte

pattern) {

this

.

pattern

= pattern;

}

public

Socket createSocket(String host,

int

port)

throws

IOException {

return

new

XorSocket(host, port,

pattern

);

}

public

int

hashCode() {

return

(

int

)

pattern

; }

public

boolean

equals(Object obj) {

return

(getClass() == obj.getClass() &&

pattern

== ((XorClientSocketFactory) obj).

pattern

);

}

}

background image

Implementacja

RMIServerSocketFactory

24

import

java.io.*;

import

java.net.*;

import

java.rmi.server.*;

public

class

XorServerSocketFactory

implements

RMIServerSocketFactory {

private

byte

pattern

;

public

XorServerSocketFactory(

byte

pattern) {

this

.

pattern

= pattern;

}

public

ServerSocket createServerSocket(

int

port)

throws

IOException {

return

new

XorServerSocket(port,

pattern

);

}

public

int

hashCode() {

return

(

int

)

pattern

; }

public

boolean

equals(Object obj) {

return

(getClass() == obj.getClass() &&

pattern

== ((XorServerSocketFactory) obj).

pattern

);

}

}

background image

Program serwera

25

import

java.io.*;

import

java.rmi.*;

import

java.rmi.server.*;

import

java.rmi.registry.*;

public

class

HelloImpl

implements

Hello {

public

HelloImpl() {

}

public

String getHello() {

return

"Hello World!"

;

}

public

static

void

main(String args[]) {

byte

pattern = (

byte

) 0xC5;

// 10100101

try

{

HelloImpl obj =

new

HelloImpl();

RMIClientSocketFactory csf =

new

XorClientSocketFactory(pattern);

RMIServerSocketFactory ssf =

new

XorServerSocketFactory(pattern);

background image

Program serwera

26

Hello stub = (Hello) UnicastRemoteObject.exportObject(obj,

0, csf, ssf);

try

{

reg = LocateRegistry.getRegistry();

}

catch

(RemoteException ex1) {

try

{

reg = LocateRegistry.createRegistry(1099);

}

catch

(RemoteException ex2) {

return

;

}

}

reg.rebind(

"HelloService"

, stub);

}

catch

(Exception e) {

e.printStackTrace();

}

}

}

background image

Program klienta

27

import

java.rmi.Naming;

import

java.rmi.registry.LocateRegistry;

import

java.rmi.registry.Registry;

public

class

HelloClient {

public

static

void

main(String args[]) {

try

{

Hello obj = (Hello)

Naming.lookup(

"rmi://localhost/HelloService"

);

System.

out

.println(obj.getHello());

}

catch

(Exception e) {

e.printStackTrace();

}

}

}

background image

Kompilacja i uruchomienie

28

1. Kompilacja:

javac *.java

2. Wygenerowanie klas łącznikowych:

rmic HelloImpl

3. Uruchomienie programu serwera:

java HelloImpl

4. Uruchomienie programu klienta:

java HelloClient

background image

RMI i SSL

29

import

java.io.IOException;

import

java.io.Serializable;

import

java.net.Socket;

import

java.rmi.server.RMIClientSocketFactory;

import

javax.net.ssl.SSLSocketFactory;

public

class

RMISSLClientSocketFactory

implements

RMIClientSocketFactory, Serializable {

public

Socket createSocket(String arg0,

int

arg1)

throws

IOException {

SSLSocketFactory factory = (SSLSocketFactory)

SSLSocketFactory.getDefault();

return

factory.createSocket(arg0, arg1);

}

}

background image

RMI i SSL

30

import

java.io.IOException;

import

java.io.Serializable;

import

java.net.ServerSocket;

import

java.rmi.server.RMIServerSocketFactory;

import

javax.net.ssl.SSLServerSocketFactory;

public

class

RMISSLServerSocketFactory

implements

RMIServerSocketFactory, Serializable{

public

ServerSocket createServerSocket(

int

arg0)

throws

IOException {

SSLServerSocketFactory factory = (SSLServerSocketFactory)

SSLServerSocketFactory.getDefault();

return

factory.createServerSocket(arg0);

}

}

background image

RMI i SSL

31

W programie serwera (

HelloImpl.java

) należy zmienić linie odpowiadające za

tworzenie obiektów

SocketFactory

na:

RMIClientSocketFactory csf = new RMISSLClientSocketFactory();

RMIServerSocketFactory ssf = new RMISSLServerSocketFactory();

UWAGA: przy uruchomieniu programu korzystającego z SSL należy uwzględnić

magazyn kluczy używanych do autoryzacji i szyfrowania.

background image

Podsumowanie

32

Bezpieczeństwo jest się jednym z priorytetów przy tworzeniu oprogramowania.

Częściowo może być ono zapewnione poprzez szyfrowanie przesyłanych informacji.

Java standardowo wspiera protokół TLS-SSL jak również jest przygotowana do

łatwej implementacji nowych rozwiązań w tej dziedzinie.


Wyszukiwarka

Podobne podstrony:
JAVA 06 Nieznany
JAVA 06 wejście i wyjście
Opracowane pytania z Testu Java 06
Java 06 Klasy Interfejsy
java 06
2008 06 Java Microedition – metody integracji aplikacji [Inzynieria Oprogramowania]
Java praca domowa 06
Java praca domowa 06
0557078326 {7AC3ACCA} Real World Java EE Night Hacks Dissecting the Business Tier [Bien 2009 06 15]
0262692767 {09B90194} Java Precisely [Sestoft 2002 06 14]
MT st w 06
Kosci, kregoslup 28[1][1][1] 10 06 dla studentow
06 Kwestia potencjalności Aid 6191 ppt
06 Podstawy syntezy polimerówid 6357 ppt
06

więcej podobnych podstron