Android:NTLM身份validation,ksoap和持久连接

在使用iOS并处理auth挑战而没有太多学习曲线之后,我发现Windows身份validation在Java / Android中的过程要复杂得多。

我尝试了多种不同的方法,所以在没有太多涉及这些方法的情况下,我会找到一个大部分工作的方法。 我现在正在使用为NTLM创建的类和ksoap为NtlmTransport创建的类

我现在通过以下方式成功进行身份validation:

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 OK
  • Setup Cache-Control:private,max-age = 0
  • 设置内容类型:text / html; 字符集= utf-8的
  • 设置服务器:Microsoft-IIS / 8.0
  • 安装X-AspNet-Version:4.0.30319
  • Setup Persistent-Auth:true
  • 安装X-Powered-By:ASP.NET
  • 设置日期:2013年9月17日星期二20:57:45 GMT
  • 设置内容长度:11549

“Persistent-Auth:true是我现在关注的主要问题。我得到的SoapObjects很好,可以从一个连接中获取我需要的数据,但是一旦我尝试访问网络再次服务,大概能够在成功validation后被击中,我无法使用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()出错没有发现身份validation问题

??

IIS成功validation用户200后,为什么要求我再次进行身份validation? 我怎样才能坚持第一次经过身份validation的挑战,以便在WebService.asmx中找到我想要的任何方法? 如有必要,需要添加/更改哪些标题以创建会话? 我错过了什么使整个NTLM流程工作并持续存在比需要通过身份validation挑战的WS方法更多?

编辑:添加库代码

这是Apache的JCIFS链接

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

我也在努力解决Android的Windows身份validation问题。 我在https://github.com/masconsult/android-ntlm上找到了android-ntlm-master。 在项目中将此类添加为库。

更改是在NtlmTransport.java类中。我在NtlmTransport类的调用方法中进行了更改=>

  public List call(String soapAction, SoapEnvelope envelope, List headers, File outputFile) throws IOException, XmlPullParserException { HttpResponse resp = null; try { //setupNtlm(urlString, user, password); DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.getAuthSchemes().register("ntlm", new NTLMSchemeFactory()); httpclient.getCredentialsProvider().setCredentials( new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), new NTCredentials(user, password, "", "") ); HttpPost httpget = new HttpPost(urlString); httpget.addHeader("soapaction", soapAction); httpget.addHeader("Content-Type", "text/xml; charset=utf-8"); byte[] requestData = null; try { requestData = createRequestData(envelope); } catch (IOException iOException) { } ByteArrayEntity byteArrayEntity = new ByteArrayEntity(requestData); httpget.setEntity(byteArrayEntity); resp = httpclient.execute(httpget); if(resp == null) { System.out.println("Response is null"); } HttpEntity respEntity = resp.getEntity(); InputStream is = respEntity.getContent(); if(is == null) { System.out.println("InputStream is null"); } parseResponse(envelope, is); } catch (Exception ex) { // ex.printStackTrace(); } if (resp != null) { return Arrays.asList(resp.getAllHeaders()); } else { return null; } } 

以下是我打电话的代码:

  SoapObject request = new SoapObject(NAMESPACE, PRODUCT_DETAILS_METHOD_NAME); request.addProperty("ListingID", Integer.parseInt(Product_ID)); NtlmTransport httpTransport = new NtlmTransport(); httpTransport.setCredentials(URL, USERNAME, PASSWORD, "",""); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = true; envelope.implicitTypes = true; envelope.setOutputSoapObject(request); httpTransport.call(PRODUCT_DETAILS_SOAP_ACTION, envelope); SoapObject response = (SoapObject) envelope.getResponse(); 

它对我有用。

您可以在此处找到更多信息: https : //suhas1989.wordpress.com/2015/01/28/ntlm-authentication-in-android/