Pregunta

Tengo una construcción de servicio web en PHP que usa Usernametoken como mecanismo de autentificación. Tengo un código del lado del cliente PHP que puede acceder a este servicio web. Ahora necesito hacer esto en Java. ¡Quizás podrías ayudarme!

Se puede acceder a este servicio utilizando 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 se analizan en este encabezado 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 acceder al servicio web sin ningún problema. Ahora necesito hacer esto en Java.

He creado los archivos necesarios, implementé un controlador para agregar un encabezado SOAP al UserNamToken. Pero cuando trato de acceder al WS siempre recibo un error "no autorizado". Creo que me falta algo mientras crea la entrada de passdigest o nonce.

Así es como los calculo:

    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 al crear el encabezado SOAP:

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

Así es como se ve el encabezado de jabón resultante:

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

¿Fue útil?

Solución

Encontré una solución. Mi problema era que olvidé agregar HEX codificando al valor nonce y a la cadena concletada. Aquí está mi solución, tal vez algunos necesiten esto.

Las funciones para crear pases, 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 para crear el mensaje 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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top