Android: NTLM-аутентификация, ksoap и постоянные соединения
После работы с iOS и решения проблем с аутентификацией без особых трудностей обучения я обнаружил, что аутентификация Windows намного сложнее процесса в Java / Android.
Я попробовал несколько разных подходов, поэтому, не вдаваясь в них, я доберусь до того, который работал по большей части. Сейчас я использую класс, созданный для NTLM и ksoap, который называется NtlmTransport
Я успешно прошел проверку подлинности следующим образом:
NtlmTransport httpTransport = new NtlmTransport();
httpTransport.setCredentials(serverURL, Login.username, Login.password, deviceIp, "DOMAINNAME");
httpTransport.call(SOAP_ACTION, envelope);
Если вы посмотрите на класс NtlmTransport, вы увидите, что он возвращает следующие заголовки из setupNtlm ():
status Line HTTP / 1.1 200 OKSetup Cache-Control: приватный, max-age = 0Setup Content-Type: text / html; кодировка = UTF-8 Настраиваемый сервер: Microsoft-IIS / 8.0 Setup X-AspNet-Version: 4.0.30319 Setup Persistent-Auth: true Настройка X-Powered-By: ASP.NETата @Tetup: вторник, 17 сентября 2013 20:57:45 GMTSetup Content-Length: 11549"Persistent-Auth: true - это основной вопрос, который меня беспокоит в настоящее время. Я получаю SoapObjects очень хорошо и могу получить нужные мне данные по этому одному соединению, но как только я пытаюсь получить доступ к снова веб-сервис, который, вероятно, может быть запущен после успешной аутентификации, я не могу получить доступ к другому методу, используя 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());
}
}
Это все прекрасно работает как фоновая задача AsyncTask, которая затем передает «xml» методу XMLPullParser.
Главный вопрос здесь - почему я получаю:
Ошибка на setSomething () Проблемы с аутентификацией не найдены
??
После того, как IIS успешно проверил пользователя с 200, почему он просит меня снова пройти аутентификацию? Как я могу сохранить эту первую проверку подлинности, чтобы попасть в любой метод, который я хочу, внутри WebService.asmx? Какие заголовки нужно добавить / изменить, чтобы создать сеанс при необходимости? Чего мне не хватает, что заставляет весь этот процесс NTLM работать и сохраняться больше, чем метод WS, который должен пройти проверку подлинности?
EDIT: добавление кода библиотеки
Вот ссылка наJCIFS от 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());
}
}
Так является ли причиной этой проблемы "NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN"? Есть ли другой флаг, который я должен установить для поддержания жизни? Кроме того, я нашел отличный ресурс для списка флагов NTLM и многого другого:http: //fossies.org/dox/jcifs-1.3.17/interfacejcifs_1_1ntlmssp_1_1NtlmFlags.htm