Android: Uwierzytelnianie NTLM, ksoap i trwałe połączenia

Po pracy z iOS i radzeniu sobie z wyzwaniami uwierzytelniania bez dużej krzywej uczenia się, odkryłem, że Uwierzytelnianie systemu Windows jest znacznie bardziej skomplikowane niż proces w Javie / Androidzie.

Spróbowałem wielu różnych podejść, więc nie wdając się zbytnio w te, przejdę do tego, który działał w przeważającej części. Teraz używam klasy utworzonej dla NTLM i ksoap o nazwie NtlmTransport

Teraz pomyślnie uwierzytelniam się w następujący sposób:

NtlmTransport httpTransport = new NtlmTransport();
            httpTransport.setCredentials(serverURL, Login.username, Login.password, deviceIp, "DOMAINNAME");
            httpTransport.call(SOAP_ACTION, envelope);

Jeśli spojrzysz na klasę NtlmTransport, zobaczysz, że zwraca następujące nagłówki z setupNtlm ():

status Line HTTP / 1.1 200 OK Konfiguracja kontroli pamięci podręcznej: prywatna, maks. Wiek = 0Setup Content-Type: text / html; charset = utf-8Setup Server: Microsoft-IIS / 8.0Setup X-AspNet-Version: 4.0.30319Setup Persistent-Auth: trueSetup X-Powered-By: ASP.NET Data ustawienia: wt, 17 września 2013 20:57:45 GMTSetup Content-Length: 11549

„Trwałe uwierzytelnianie: prawda jest tym, co mnie obecnie niepokoi. Dostaję SoapObjects w porządku i mogę uzyskać potrzebne dane z tego jednego połączenia, ale jak tylko spróbuję uzyskać dostęp do ponownie usługa internetowa, która prawdopodobnie zostanie trafiona po udanym uwierzytelnieniu, nie mogę uzyskać dostępu do innej metody za pomocą HttpTransportSE:

private void setSomething() {

    xml = null;
    final String SOAP_ACTION = "http://this.ismy.org/AWebServiceMethod";
    final String METHOD_NAME = "AWebServiceMethod";
    final String URL = protocol + "://" + host  + ":" + port + "/WebService.asmx";
    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.dotNet = true;
    envelope.setOutputSoapObject(request);
    envelope.implicitTypes = true;
    envelope.setAddAdornments(false);

    try
    {
        HttpTransportSE transport = new HttpTransportSE(URL);
        transport.debug = true;
        transport.call(SOAP_ACTION, envelope);
        xml = transport.responseDump.toString();
        Log.d(TAG, xml);
    }
    catch(SocketException ex)
    {
        Log.e("SocketException : " , "Error on setSomething() " + ex.getMessage());
    }
    catch (Exception e)
    {
        Log.e("Exception : " , "Error on setSomething() " + e.getMessage());
    }
}

To wszystko działa dobrze jako zadanie w tle AsyncTask, które następnie przekazuje „xml” do metody XMLPullParser.

Główne pytanie tutaj brzmi: dlaczego otrzymuję:

Błąd na setSomething () Nie znaleziono problemów z uwierzytelnieniem

??

Po tym, jak IIS pomyślnie zweryfikuje użytkownika przy użyciu 200, dlaczego prosi mnie o ponowne uwierzytelnienie? Jak mogę utrzymać to pierwsze uwierzytelnione wyzwanie, aby trafić w dowolną metodę w WebService.asmx? Jakie nagłówki należy dodać / zmienić, aby w razie potrzeby utworzyć sesję? Czego mi brakuje, co sprawia, że cały proces NTLM działa i trwa dłużej niż metoda WS, która musi przejść wyzwania uwierzytelnienia?

EDIT: Dodawanie kodu biblioteki

Oto link doJCIFS z Apache

public static final class JCIFSEngine implements NTLMEngine {

    private static final int TYPE_1_FLAGS =
            NtlmFlags.NTLMSSP_NEGOTIATE_56 |
                    NtlmFlags.NTLMSSP_NEGOTIATE_128 |
                    NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2 |
                    NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
                    NtlmFlags.NTLMSSP_REQUEST_TARGET;

    public String generateType1Msg(final String domain, final String workstation)
            throws NTLMEngineException {
        final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation);
        return jcifs.util.Base64.encode(type1Message.toByteArray());
    }

    public String generateType3Msg(final String username, final String password,
                                   final String domain, final String workstation, final String challenge)
            throws NTLMEngineException {
        Type2Message type2Message;
        try {
            type2Message = new Type2Message(jcifs.util.Base64.decode(challenge));
        } catch (final IOException exception) {
            throw new NTLMEngineException("Invalid NTLM type 2 message", exception);
        }
        final int type2Flags = type2Message.getFlags();
        final int type3Flags = type2Flags
                & (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));
        final Type3Message type3Message = new Type3Message(type2Message, Login.password, "",
                Login.username, deviceIp, type3Flags);

            System.out.println("type3Message: " + type3Message.toByteArray());

        return jcifs.util.Base64.encode(type3Message.toByteArray());
    }
}

Czy więc „NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN” powoduje ten problem? Czy jest jakaś inna flaga, którą powinienem ustawić dla podtrzymania życia? Znalazłem też świetne źródło listy flag NTLM i nie tylko:http: //fossies.org/dox/jcifs-1.3.17/interfacejcifs_1_1ntlmssp_1_1NtlmFlags.htm

questionAnswers(1)

yourAnswerToTheQuestion