3

Android から NAV Web サービスを利用する必要があります。「Upper」機能を備えた「Letters」コードユニットを取得しました。

PC で NAV Web サービス (NTLM 認証) をセットアップし、ファイアウォールをオフにしました (このサービスがネットワーク内の他のデバイスで見えるようにするため)。このサービスは、(PC アカウントの) ログイン/パスを入力した後、ブラウザ (Android デバイスでも) でアクセスできます。このコードを使用すると、「呼び出し」で 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) 認証情報を送信するにはどうすればよいですか? いくつかの方法を試しましたが、結果は常に同じです... この問題の経験はありますか?

4

5 に答える 5

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();
        }
于 2013-09-21T12:22:11.447 に答える
1

1) Jars jcifs-1.3.17.jar ksoap2-android-assembly-3.0.0-jar-with-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) パラメータ url,"username","password","domainName","SystemName" を指定してこのメ​​ソッドを呼び出します

 NtlmTransport ntlm = new NtlmTransport(url, "username", "password", "domainName","SystemName");

4) Soap Envelope で構成される Soap Request を送信します。

 ntlm.call("namespace/methodname", soapEnvelope);
于 2014-01-24T07:52:50.003 に答える
0

これが、http 認証がどのように機能するかです。フィドラーを使用して、仲介者が何をしているかを確認できます。それを取り除きたい場合は、同じことをしなければなりません:)

そうは言っても、Navision での認証は、SPNEGO または NTLM を使用するため、ピクニックではありません。NTLM 用に構成できる場合は、 android-ntlmを使用して作業を完了できる可能性があります。を除いて、プンギの答えに似ていますhttpclient.getAuthSchemes().register("ntlm", new NTLMSchemeFactory());

于 2013-03-30T07:25:45.470 に答える
0

こんにちは、使用しようとしましたか

var httpClient = new DefaultHttpClient();
NTCredentials nt = new NTCredentials("user", "pass", "", "domain");
httpClient.GetCredentialsProvider().SetCredentials(AuthScope.ANY, nt);
于 2013-03-20T20:42:28.897 に答える
0

NAV サービスを読み取り、この C# WS を介して Android が NAV WS と通信する別の Web サービス (C# で記述され、NAV サーバーが実行されているのと同じ PC 上で実行される) の作成によって解決されました。

于 2013-03-15T11:48:16.827 に答える