2011-07-24 9 views
5

Mam wbudowaną usługę sieciową w PHP, która używa UsernameToken jako mechanizmu uwierzytelniania. Mam kod po stronie klienta PHP, który może uzyskać dostęp do tej usługi WWW. Teraz muszę to zrobić w Javie. Może ty możesz mi pomóc!Klient usługi Java Webservice UsernameToken odpowiadający PHP

Usługa ta jest dostępna za pomocą następującego kodu php:

$password="super_secure_pass"; 
$timestamp=gmdate('Y-m-d\TH:i:s\Z'); 
$nonce=mt_rand(); 
$passdigest=base64_encode(pack('H*',sha1(pack('H*',$nonce).pack('a*',$timestamp).pack('a*',$password)))); 
$nonce=base64_encode(pack('H*',$nonce)) 

Wartości te uzyskać analizowany w tym nagłówku SOAP.

<wsse:Security SOAP-ENV:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
<wsse:UsernameToken> 
    <wsse:Username>'.$username.'</wsse:Username> 
    <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">'.$passdigest.'</wsse:Password> 
    <wsse:Nonce>'.$nonce.'</wsse:Nonce> 
    <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">'.$timestamp.'</wsu:Created> 
    </wsse:UsernameToken> 
</wsse:Security> 

Za pomocą tego kodu mogę uzyskać dostęp do usługi internetowej bez żadnych problemów. Teraz muszę to zrobić w Javie.

Utworzyłem potrzebne pliki, zaimplementowałem program obsługi, aby dodać nagłówek mydła z nazwą UsernameToken. Ale gdy próbuję uzyskać dostęp do WS, zawsze otrzymuję komunikat "Nie autoryzowano". Myślę, że brakuje mi czegoś podczas tworzenia wpisu passdigest lub nonce.

Oto jak je obliczyć:

Random generator = new Random(); 
    String nonceString = String.valueOf(generator.nextInt(999999999)); 
    String createTime=localToGmtTimestamp();//Returns a date with format (SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")) 
    String pass="super_secure_pass"; 
    String tmp = AeSimpleSHA1.SHA1(nonce + createTime + pass); 
    encodedPass = Base64.encodeBytes(tmp.getBytes()); 

Wartości te zostaną wykorzystane przy tworzeniu nagłówka mydła:

SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope(); 
    SOAPHeader header = envelope.addHeader(); 
    SOAPElement security = header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
    SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse"); 
    SOAPElement username = usernameToken.addChildElement("Username", "wsse"); 
    username.addTextNode(user); 

    SOAPElement password = usernameToken.addChildElement("Password", "wsse"); 
    password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"); 
    password.addTextNode(encodedPass); 

    SOAPElement nonce = 
     usernameToken.addChildElement("Nonce", "wsse"); 
    nonce.addTextNode(Base64.encodeBytes(nonceString.getBytes())); 

    SOAPElement created = usernameToken.addChildElement("Created", "wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); 

    created.addTextNode(creatTime); 

To właśnie otrzymany nagłówek mydło wygląda następująco:

<S:Header> 
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
     <wsse:UsernameToken> 
      <wsse:Username>myusername</wsse:Username> 
      <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">ZDM4MjkwNzNlNTc3MjNmMTY4MjgyYWQ1ZjllN2JlZmJmNGY2NDE4MA==</wsse:Password> 
      <wsse:Nonce>NTU5NzA2Mjkw</wsse:Nonce> 
      <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2011-07-24T11:41:55Z</wsu:Created> 
     </wsse:UsernameToken> 
    </wsse:Security> 
</S:Header> 

Czy ktoś widzi, co robię źle?

+0

Dziękujemy za opublikowanie tego kodu. Szukałem czegoś podobnego. – jjwdesign

Odpowiedz

8

Znalazłem rozwiązanie. Mój problem polegał na tym, że zapomniałem dodać kodu szesnastkowego do wartości NONCE i do uzyskanego łańcucha. Oto moje rozwiązanie, może niektórzy tego potrzebują.

Funkcje stworzyć podanie itd .:

private String calculatePasswordDigest(String nonce, String created, String password) { 
     String encoded = null; 
     try { 
      String pass = hexEncode(nonce) + created + password; 
      MessageDigest md = MessageDigest.getInstance("SHA1"); 
      md.update(pass.getBytes()); 
      byte[] encodedPassword = md.digest(); 
      encoded = Base64.encodeBytes(encodedPassword); 
     } catch (NoSuchAlgorithmException ex) { 
      Logger.getLogger(HeaderHandler.class.getName()).log(Level.SEVERE, null, ex); 
     } 

     return encoded; 
    } 

    private String hexEncode(String in) { 
     StringBuilder sb = new StringBuilder(""); 
     for (int i = 0; i < (in.length() - 2) + 1; i = i + 2) { 
      int c = Integer.parseInt(in.substring(i, i + 2), 16); 
      char chr = (char) c; 
      sb.append(chr); 
     } 
     return sb.toString(); 
    } 

kod do budowania komunikatu SOAP:

String timestamp = HeaderHandler.localToGmtTimestamp(); 
String pass = "password"; 
String user = "username"; 
String nonceString = getNonce(); 


String dig=calculatePasswordDigest(nonceString, timestamp, pass); 


SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope(); 
SOAPHeader header = envelope.addHeader(); 

SOAPElement security = 
header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 


SOAPElement usernameToken = 
security.addChildElement("UsernameToken", "wsse"); 


SOAPElement username = 
usernameToken.addChildElement("Username", "wsse"); 
username.addTextNode(user); 

SOAPElement password = 
usernameToken.addChildElement("Password", "wsse"); 
password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"); 
password.addTextNode(dig); 

SOAPElement nonce = 
usernameToken.addChildElement("Nonce", "wsse"); 
nonce.addTextNode(Base64.encodeBytes(hexEncode(nonceString).getBytes())); 

SOAPElement created = usernameToken.addChildElement("Created", "wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); 
created.addTextNode(timestamp); 
+0

Witam, czy mógłbyś podpowiedzieć, co robi getNonce()? Drugie pytanie: z której klasy Base64 korzystasz? Mój (z apache.commons) nie ma funkcji encodeBytes(). Pozdrawiamy –