Komunikace se zabezpecenymi webovymi sluzbami


Dnes jsem se trapil s tvorbou klienta, ktery se mel pripojit na vzdalenou webovou sluzbu s klientskym certifikatem a predevsim – autentikovat se pomoci jmena a hesla. Nakonec se chyba ukazala byt trochu jinde, nez jsem ji cekal, ale kdyz uz jsem s tim stravil cas, tak to tu trochu popisu, kdyby nahodou nekdo resil podobny problem.

Nejprve ona chyba – mam zdrojak pro klienta vygenerovany pomoci wsimportu a protoze jsem se snazil o univerzalni reseni, adresa koncoveho bodu je v .properties souboru. Lokalne mam ovsem ulozeny wsdl, na ktery se odkazuju pomoci anotace @WebServiceClient ve tride klienta:

[code language=“java“]@WebServiceClient(
name = "myService",
targetNamespace = "http://www.shmoula.cz/my/service",
wsdlLocation = "META-INF/wsdl/myService.wsdl")
public class MyServiceClient extends Service{
[/code]

No a tohle byl muj problem – toto lokalni wsdl se neshodovalo s deskriptorem na druhe strane (odstranil jsem policy cast), takze mi server porad odmital pozadavky:

[code language=“plain“]javax.xml.ws.WebServiceException: Failed to access the WSDL at: https://shmoula.cz:8080/myService?wsdl. It failed with:
Connection refused.
[/code]

Stacilo zmenit wsdlLocation na adresu deskriptoru na serveru a vse uz bezi v poradku. Hadam, ze kdyby lokalni wsdl presne odpovidalo tomu na serveru, fungovalo by to taky. Ted ale to podstatnejsi – jak autentikovat uzivatele?

Nejprve mejme vygenerovany a naimportovany certifikat v trusted certs, napr. pomoci keytool:

[code language=“bash“]keytool -import -alias shmoula.cz -file certifikat.shmoula.cz.der -keystore <J2EE_HOME>/domains/domain1/config/cacerts.jks
[/code]

Potom budeme potrebovat vlastni implementaci tridy Authenticator, kterou zajistime, aby byly autentikacni informace predavany pouze pri zabezpecenem spojeni:

[code language=“java“]package cz.shmoula.klient;

import java.net.Authenticator;
import java.net.PasswordAuthentication;

public class BasicHTTPAuthenticator extends Authenticator {
private String userName;
private String password;

public BasicHTTPAuthenticator(String userName, String password){
this.userName = userName;
this.password = password;
}

@Override
protected PasswordAuthentication getPasswordAuthentication(){
if (this.getRequestingProtocol().equalsIgnoreCase("https"))
return new PasswordAuthentication(userName, password.toCharArray());
else
return null;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}
[/code]

V aplikaci je potom nutne nejprve nastavit tento autentikator a teprve pote vytvorit instanci klienta:

[code language=“java“]URL baseUrl = cz.shmoula.klient.MyServiceClient.class.getResource(".");
URL url = new URL(baseUrl, "https://shmoula.cz:8080/myService?wsdl");
QName qName = new QName("http://www.shmoula.cz/myservice", "myService");

Authenticator.setDefault(new BasicHTTPAuthenticator("jmeno", "heslo"));
MyServiceIface service = new MyServiceClient(url, qName).getMyServicePort();
[/code]

Pote je nutne jeste poupravit kontext pozadavku pomoci BindingProvidera a je mozne se pustit do volani vzdalenych metod, vse zabezpeceno:

[code language=“java“]BindingProvider bp = (BindingProvider) service;
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "jmeno");
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "heslo");
MyServiceResponse resp = service.makeCall(foo, bar);
[/code]

Abych pravdu rekl, prestava se mi to libit cim dal tim vic, asi se vratim k JSONu. Podstatne je, ze to mam z krku.


Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *