2011-07-24 22 views
5

Tengo una estructura de servicio web en PHP que usa UsernameToken como mecanismo de autenticación. Tengo un código de cliente PHP que puede acceder a este servicio web. Ahora necesito hacer esto en Java. ¡Quizás podrías ayudarme!Java Webservice Cliente Nombre de usuarioToken equivalente a PHP

Este servicio se puede acceder mediante el siguiente código 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)) 

Estos valores quedan analizan en esta cabecera de jabón.

<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> 

Con este código Puedo tener acceso al servicio web sin ningún problema. Ahora necesito hacer esto en Java.

He creado los archivos necesarios, implementado un controlador para agregar un encabezado de soap con UsernameToken. Pero cuando intento acceder al WS, siempre aparece el error "No autorizado". Creo que me falta algo al crear la entrada passdigest o nonce.

Aquí es cómo los calcule:

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()); 

Estos valores se utilizarán durante la creación de la cabecera de jabón:

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); 

Esto es lo que la cabecera de jabón resultante se parece a:

<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> 

¿Alguien ve lo que estoy haciendo mal?

+0

Gracias por publicar este código. Estaba buscando algo similar. – jjwdesign

Respuesta

8

Encontré una solución. Mi problema fue que olvidé agregar una codificación hexadecimal al valor NONCE y a la cadena concatenada. Aquí está mi solución, tal vez algunos lo necesiten.

Las funciones para crear pase etc .:

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(); 
    } 

Código de construir el mensaje de jabón:

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

Hola, ¿podría darnos una pista de lo que hace getNonce()? Segunda pregunta: ¿Qué clase Base64 usas? El mío (de apache.commons) no tiene la función encodeBytes(). Saludos cordiales –

Cuestiones relacionadas