我需要从android使用NAV Web服务。 我得到了“Letters”codeunit和“Upper”函数。
我已经在我的PC上设置了NAV Web服务(NTLM身份验证)并关闭了防火墙(以便在我的网络中的其他设备上显示此服务)。输入登录/通过(我的PC帐户)后,可以在浏览器(也在adroid设备上)访问该服务。 如果我使用this code,它会在END_DOCUMENT null异常的“调用”中崩溃... 那是因为认证吗?
如果我使用此代码连接
HttpGet request = new HttpGet("http://[myPC'sIP]:7047/DynamicsNAV/WS/SystemService"); HttpResponse response = client.execute(request);
我收到401错误,但只是指定了IP
HttpGet request = new HttpGet("http://[myPC'sIP]"); HttpResponse response = client.execute(request);
返回代码200(ok) 我该如何发送凭证?我试过几种方法,但结果总是一样的...... 你有这个问题的经验吗?
答案 0 :(得分:1)
我使用soap_action做同样的事情并且它像魅力一样工作,看看下面的代码是否有助于你:
String namespace = "urn:microsoft-dynamics-schemas/codeunit/NavisionWS";
String url = "http://IP:7047/DynamicsNAV/WS/Codeunit/NavisionWS";
String soap_action = "urn:microsoft-dynamics-schemas/codeunit/NavisionWS:GetLoginInfo";
String method_name = "GetLoginInfo";
try
{
SoapObject request = new SoapObject(namespace, method_name);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE transport = new HttpTransportSE(url);
transport.call(soap_action, envelope); // Receive Error here!
SoapObject result = (SoapObject) envelope.getResponse();
great = result.toString();
}
catch (Exception e)
{
e.printStackTrace();
great = e.toString();
Toast.makeText(this, great, Toast.LENGTH_LONG).show();
}
答案 1 :(得分:1)
1)在坛子下面添加 的 JCIFS-1.3.17.jar 强> 的 ksoap2-机器人组装-3.0.0-罐与 - dependencies.jar 强>
2)创建这些java类 的 JCIFSEngine.java 强>
package com.demo.Authentication;
import jcifs.ntlmssp.NtlmFlags;
import jcifs.ntlmssp.Type1Message;
import jcifs.ntlmssp.Type2Message;
import jcifs.ntlmssp.Type3Message;
import jcifs.util.Base64;
import org.apache.http.impl.auth.NTLMEngine;
import org.apache.http.impl.auth.NTLMEngineException;
import java.io.IOException;
/**
* Class taken from http://hc.apache.org/httpcomponents-client-ga/ntlm.html
*/
public 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 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(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, password, domain,
username, workstation, type3Flags);
return Base64.encode(type3Message.toByteArray());
}
}
<强> NtlmTransport.java 强>
package com.demo.Authentication;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthSchemeFactory;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.auth.NTLMScheme;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.ServiceConnection;
import org.ksoap2.transport.Transport;
import org.xmlpull.v1.XmlPullParserException;
public class NtlmTransport extends Transport {
static final String ENCODING = "utf-8";
private final DefaultHttpClient client = new DefaultHttpClient();
private final HttpContext localContext = new BasicHttpContext();
private String urlString;
private String user;
private String password;
private String ntDomain;
private String ntWorkstation;
public static String AuthenticationCode;
public NtlmTransport(String url, String user, String password,
String domain, String workStation) {
this.urlString = url;
this.user = user;
this.password = password;
this.ntDomain = domain;
this.ntWorkstation = workStation;
}
public void setCredentials(String url, String user, String password,
String domain, String workStation) {
this.urlString = url;
this.user = user;
this.password = password;
this.ntDomain = domain;
this.ntWorkstation = workStation;
}
public List call(String targetNamespace, SoapEnvelope envelope, List headers)
throws IOException, XmlPullParserException {
return call(targetNamespace, envelope, headers, null);
}
public List call(String soapAction, SoapEnvelope envelope, List headers, File outputFile)
throws IOException, XmlPullParserException {
if (outputFile != null) {
// implemented in HttpTransportSE if you are willing to port..
throw new RuntimeException("Writing to file not supported");
}
HttpResponse resp = null;
setupNtlm(urlString, user, password);
try {
// URL url = new URL(urlString);
HttpPost httppost = new HttpPost(urlString);
setHeaders(soapAction, envelope, httppost, headers);
resp = client.execute(httppost, localContext);
HttpEntity respEntity = resp.getEntity();
InputStream is = respEntity.getContent();
parseResponse(envelope, is);
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println("RESPONSE STATUS CODE :"+resp.getStatusLine().getStatusCode());
if (resp != null) {
return Arrays.asList(resp.getAllHeaders());
} else {
return null;
}
}
private void setHeaders(String soapAction, SoapEnvelope envelope, HttpPost httppost, List headers) {
byte[] requestData = null;
try {
requestData = createRequestData(envelope);
} catch (IOException iOException) {
}
ByteArrayEntity byteArrayEntity = new ByteArrayEntity(requestData);
httppost.setEntity(byteArrayEntity);
httppost.addHeader("User-Agent", org.ksoap2.transport.Transport.USER_AGENT);
// SOAPAction is not a valid header for VER12 so do not add
// it
// @see "http://code.google.com/p/ksoap2-android/issues/detail?id=67
if (envelope.version != SoapSerializationEnvelope.VER12) {
httppost.addHeader("SOAPAction", soapAction);
}
if (envelope.version == SoapSerializationEnvelope.VER12) {
httppost.addHeader("Content-Type", Transport.CONTENT_TYPE_SOAP_XML_CHARSET_UTF_8);
} else {
httppost.addHeader("Content-Type", Transport.CONTENT_TYPE_XML_CHARSET_UTF_8);
}
// Pass the headers provided by the user along with the call
if (headers != null) {
for (int i = 0; i < headers.size(); i++) {
HeaderProperty hp = (HeaderProperty) headers.get(i);
httppost.addHeader(hp.getKey(), hp.getValue());
}
}
}
// Try to execute a cheap method first. This will trigger NTLM authentication
public void setupNtlm(String dummyUrl, String userId, String password) {
try {
((AbstractHttpClient) client).getAuthSchemes().register("ntlm", new NTLMSchemeFactory());
NTCredentials creds = new NTCredentials(userId, password, ntWorkstation, ntDomain);
client.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpGet httpget = new HttpGet(dummyUrl);
HttpResponse response1 = client.execute(httpget, localContext);
HttpEntity entity1 = response1.getEntity();
Header[] hArray = response1.getAllHeaders();
int size = hArray.length;
AuthenticationCode = String.valueOf(response1.getStatusLine().getStatusCode());
System.out.println("AUTHENTICATION STATUS CODE :"+response1.getStatusLine().getStatusCode());
/* for (int i = 0; i < size; i ++) {
Header h = hArray[i];
if (h.getName().equals("WWW-Authenticate")) {
entity1.consumeContent();
throw new Exception("Failed Authentication");
}
}*/
entity1.consumeContent();
} catch (Exception ex) {
ex.printStackTrace();
}
}
//NTLM Scheme factory
private class NTLMSchemeFactory implements AuthSchemeFactory {
public AuthScheme newInstance(final HttpParams params) {
// see http://www.robertkuzma.com/2011/07/
// manipulating-sharepoint-list-items-with-android-java-and-ntlm-authentication/
return new NTLMScheme(new JCIFSEngine());
}
}
public ServiceConnection getServiceConnection() throws IOException
{
throw new IOException("Not using ServiceConnection in transport");
}
public String getHost() {
String retVal = null;
try {
retVal = new URL(url).getHost();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return retVal;
}
public int getPort() {
int retVal = -1;
try {
retVal = new URL(url).getPort();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return retVal;
}
public String getPath() {
String retVal = null;
try {
retVal = new URL(url).getPath();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return retVal;
}
}
3) 使用paramater url,“username”,“password”,“domainName”,“SystemName”调用此方法
NtlmTransport ntlm = new NtlmTransport(url, "username", "password", "domainName","SystemName");
4)发送包含Soap Envelope的Soap Request。
ntlm.call("namespace/methodname", soapEnvelope);
答案 2 :(得分:0)
通过创建另一个Web服务(在C#上编写,在运行NAV服务器的同一台PC上运行)来解决,该服务读取NAV服务并通过此C#WS与NAV WS进行通信
答案 3 :(得分:0)
你好,你试过用
var httpClient = new DefaultHttpClient();
NTCredentials nt = new NTCredentials("user", "pass", "", "domain");
httpClient.GetCredentialsProvider().SetCredentials(AuthScope.ANY, nt);
答案 4 :(得分:0)
这是http身份验证supposed to work的方式。您可以使用fiddler查看您的中介正在做什么。如果你想摆脱它,你将不得不做同样的事情:)
据说使用Navision认证不是野餐,因为它使用SPNEGO或NTLM。如果您可以配置NTLM,则可以使用android-ntlm来完成工作。看起来类似于pungggi的答案,httpclient.getAuthSchemes().register("ntlm", new NTLMSchemeFactory());