كيف يمكنني الحصول على JCIFS للعب بشكل جيد مع محور Apache

StackOverflow https://stackoverflow.com/questions/916820

  •  06-09-2019
  •  | 
  •  

سؤال

أحتاج إلى توصيل APACHE AXIS 1.4 إلى Webservice يستخدم مصادقة NTLM لتقييد الوصول إلى عملياتها. أتوقع استخدام Samba JCIFS للتعامل مع مصافحة NTLM.

وجدت

http://hc.apache.org/httpcomponents-client/ntlm.html

مما يعطيني اتجاهات رائعة لكيفية أسلاك HTTPClient 4.0 مع JCIFS.

المشكلة هي، يريد المحور استخدام عميل HTTP 3.0 و APIs تبدو مختلفة للغاية.

هناك 2 إمكانيات أستطيع أن أرى

  1. اكتب كائنا للمحور الذي يتيح له توصيل HTTPClient 4.
  2. اكتشف كيفية سلك HTTPClient 3.0 مع Samba JCIFS.

الرقم 1. يبدو غير تافهة، ولكنه ممكن رقم 2. لا يمكنني العثور على أي رسائل مشجعة على الويب التي تصف كيفية القيام بذلك.

سؤالي هو: هل اتصل بأي شخص بنجاح Samba JCIFS مع HTTPClient 3.0؟ هل قام أي شخص بالفعل بإنشاء كائن HTTPSender Axis يعمل مع HTTPClient 4؟

هل هناك بعض البديل الأفضل الذي لم أفكر فيه؟

هل كانت مفيدة؟

المحلول

أخيرا الحصول على حل لهذا.

المشكلة

يستخدم Abache Axis Apache HTTPClient والتي توفر تنفيذ NTLM الخاص بها.
لكن هذا التنفيذ غير مكتمل؛ هذا يدعم فقط مصادقة LM البدائية.
النظام الذي أحتاجه للاتصال به يصر على مصادقة NTLM الأكثر حداثة.

لذلك فشل خادم الويب الخاص بي للمصادقة عند استخدام عميل Apache HTTP مع NTLM.

هذا فعلا بعد ذلك يدخل حلقة لا حصر لها HTTPClient لن تتوقف أبدا عن المحاولة والفشل في المصادقة.

الحل

يدعم JCIFS بشكل كامل جميع الإصدارات الثلاثة من المصافحة NTLM.
لدي نسخ ولصق org.apache.commons.httpclient.auth.NTLM في صفي الخاص (يتم الإعلان عن "نهائي" من أجل هزيمة الميراث)

لقد قمت بالكتابة فوق الطريقة

public String getType3Message(
        String user, String password, String host, String domain,
        byte[] nonce) throws AuthenticationException

لبناء مثيل jcifs.ntlmssp.Type3Messageواستخدام هذا الكائن لإرجاع Type3Message التي تحتوي على مصادقة NTML التي تم إنشاؤها بشكل صحيح.

ثم أحتاج إلى إنشاء مثيل خاص بي org.apache.commons.httpclient.auth.AuthSchemeللاستفادة من تنفيذ NTLM الجديد هذا. يتصلorg.apache.commons.httpclient.auth.AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, MyNewAuthScheme.class)

ابدأ تشغيل كعب نقطة النهاية WS.

ويعمل !!!

نصائح أخرى

شكرا جزيلا الكثير بن، عمل جيد. لحل بلدي أحتاج إلى تحسينتين، بناء على فصولك.

1) فئة jcifsntlmscheme.

لقد تغيرت الواجهة في JCIFS (أستخدم الإصدار 1.3.14). مطلوب علامة NTLM، لست متأكدا حقا ولكن 0x82 يعمل بالنسبة لي.

int flags = Type3Message.NTLMSSP_NEGOTIATE_OEM | Type3Message.NTLMSSP_NEGOTIATE_LM_KEY;

Type3Message msg3 =
        new Type3Message(msg2, ntcredentials.getPassword(),
        ntcredentials.getDomain(), ntcredentials.getUserName(), ntcredentials.getHost(), flags);

2) فئة ntlmjcifscredentials.

 DefaultHttpParams.setHttpParamsFactory(paramFact);

هذا يعمل بشكل جيد للاتصال الأول. يبدو أن الإعداد العالمي. ربما ليس آمنا حقا آمنة. أحتاج إلى بيانات الاعتماد على قاعدة الاتصالات. لذلك أسقطت هذه الفئة وإدراج المصادقة المدمجة مباشرة بعد إنشاء كعب Webservice:

jcifs.Config.setProperty("jcifs.encoding", "ASCII");
AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, JcifsNtlmScheme.class);

Authenticator authenticator = new Authenticator();
List<String> authScheme = new ArrayList<String>();
authScheme.add(Authenticator.NTLM);
authScheme.add(Authenticator.BASIC);
authenticator.setAuthSchemes(authScheme);
authenticator.setUsername(myusername);
authenticator.setPassword(mypassword);
authenticator.setHost(servername);
authenticator.setDomain(domain);        
exService._getServiceClient().getOptions().setProperty(HTTPConstants.AUTHENTICATE, authenticator);       
exService._getServiceClient().getOptions().setProperty(HTTPConstants.CHUNKED, Boolean.FALSE);
exService._getServiceClient().getOptions().setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Boolean.TRUE);

ردا على تعليق سيرجي ...

لدي اثنين من clases في الحل الخاص بي. مخطط ترخيص مثل هذا


import java.io.IOException;

import jcifs.ntlmssp.Type1Message;
import jcifs.ntlmssp.Type2Message;
import jcifs.ntlmssp.Type3Message;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.auth.AuthChallengeParser;
import org.apache.commons.httpclient.auth.AuthScheme;
import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.commons.httpclient.auth.InvalidCredentialsException;
import org.apache.commons.httpclient.auth.MalformedChallengeException;
import org.apache.commons.httpclient.auth.NTLMScheme;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * AuthScheme that delegates the work of reading and writing NTLM messages to
 * the JCIFS implementation
 * 
 * directly inspired by org.apache.commons.httpclient.auth.NTLMScheme
 * 
 *
 * This software is based upon voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * .
 *
 */
public class JcifsNtlmScheme implements AuthScheme
{
    /** Log object for this class. */
    private static final Log LOG = LogFactory.getLog(NTLMScheme.class);

    /** NTLM challenge string. */
    private String ntlmchallenge = null;

    private static final int UNINITIATED = 0;
    private static final int INITIATED = 1;
    private static final int TYPE1_MSG_GENERATED = 2;
    private static final int TYPE2_MSG_RECEIVED = 3;
    private static final int TYPE3_MSG_GENERATED = 4;
    private static final int FAILED = Integer.MAX_VALUE;

    /** Authentication process state */
    private int state;

    /**
     * Default constructor for the NTLM authentication scheme.
     * 
     * @since 3.0
     */
    public JcifsNtlmScheme()
    {
        super();
        this.state = UNINITIATED;
    }

    /**
     * Constructor for the NTLM authentication scheme.
     * 
     * @param challenge
     *            The authentication challenge
     * 
     * @throws MalformedChallengeException
     *             is thrown if the authentication challenge is malformed
     */
    public JcifsNtlmScheme(final String challenge)
            throws MalformedChallengeException
    {
        super();
        processChallenge(challenge);
    }

    /**
     * Processes the NTLM challenge.
     * 
     * @param challenge
     *            the challenge string
     * 
     * @throws MalformedChallengeException
     *             is thrown if the authentication challenge is malformed
     * 
     * @since 3.0
     */
    public void processChallenge(final String challenge)
            throws MalformedChallengeException
    {
        String s = AuthChallengeParser.extractScheme(challenge);
        if (!s.equalsIgnoreCase(getSchemeName()))
        {
            throw new MalformedChallengeException("Invalid NTLM challenge: "
                    + challenge);
        }
        int i = challenge.indexOf(' ');
        if (i != -1)
        {
            s = challenge.substring(i, challenge.length());
            this.ntlmchallenge = s.trim();
            this.state = TYPE2_MSG_RECEIVED;
        }
        else
        {
            this.ntlmchallenge = "";
            if (this.state == UNINITIATED)
            {
                this.state = INITIATED;
            }
            else
            {
                this.state = FAILED;
            }
        }
    }

    /**
     * Tests if the NTLM authentication process has been completed.
     * 
     * @return true if Basic authorization has been processed,
     *         false otherwise.
     * 
     * @since 3.0
     */
    public boolean isComplete()
    {
        return this.state == TYPE3_MSG_GENERATED || this.state == FAILED;
    }

    /**
     * Returns textual designation of the NTLM authentication scheme.
     * 
     * @return ntlm
     */
    public String getSchemeName()
    {
        return "ntlm";
    }

    /**
     * The concept of an authentication realm is not supported by the NTLM
     * authentication scheme. Always returns null.
     * 
     * @return null
     */
    public String getRealm()
    {
        return null;
    }

    /**
     * Unsupported.
     */
    public String getID()
    {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the authentication parameter with the given name, if available.
     * 
     * 

* لا توجد معلمات صالحة للمصادقة NTLM بحيث ترجع هذه الطريقة * دائما NULL. *

* * @param name * The name of the parameter to be returned * * @return the parameter with the given name */ public String getParameter(String name) { if (name == null) { throw new IllegalArgumentException("Parameter name may not be null"); } return null; } /** * Returns true. NTLM authentication scheme is connection based. * * @return true. * * @since 3.0 */ public boolean isConnectionBased() { return true; } /** * Unsupported. */ public static String authenticate( final NTCredentials credentials, final String challenge) throws AuthenticationException { throw new UnsupportedOperationException(); } /** * Unsupported. */ public static String authenticate( final NTCredentials credentials, final String challenge, String charset) throws AuthenticationException { throw new UnsupportedOperationException(); } /** * Unsupported. */ public String authenticate( Credentials credentials, String method, String uri) throws AuthenticationException { throw new UnsupportedOperationException(); } /** * Produces NTLM authorization string for the given set of * {@link Credentials}. * * @param credentials * The set of credentials to be used for athentication * @param method * The method being authenticated * * @throws InvalidCredentialsException * if authentication credentials are not valid or not applicable * for this authentication scheme * @throws AuthenticationException * if authorization string cannot be generated due to an * authentication failure * * @return an NTLM authorization string * * @since 3.0 */ public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException { LOG.trace("enter NTLMScheme.authenticate(Credentials, HttpMethod)"); if (this.state == UNINITIATED) { throw new IllegalStateException( "NTLM authentication process has not been initiated"); } NTCredentials ntcredentials = null; try { ntcredentials = (NTCredentials) credentials; } catch (ClassCastException e) { throw new InvalidCredentialsException( "Credentials cannot be used for NTLM authentication: " + credentials.getClass().getName()); } byte[] msgBytes = null; String response = null; if (this.state == INITIATED) { Type1Message msg = new Type1Message(); // @see http://davenport.sourceforge.net/ntlm.html#theType1Message // dont' support Unicode // negotiate OEM // request authentication realm in Type2 response // not signed // not encrypted // not authenticated // no lan manager key // negotiate NTLM msg.setFlags(0x5206); msg.setSuppliedWorkstation(ntcredentials.getHost()); msg.setSuppliedDomain(ntcredentials.getDomain()); msgBytes = msg.toByteArray(); this.state = TYPE1_MSG_GENERATED; } else if (this.state == TYPE2_MSG_RECEIVED) { byte[] msg2Bytes = Base64.decodeBase64(EncodingUtil.getBytes( this.ntlmchallenge, method.getParams().getCredentialCharset())); try { Type2Message msg2 = new Type2Message(msg2Bytes); Type3Message msg3 = new Type3Message(msg2, ntcredentials.getPassword(), ntcredentials.getDomain(), ntcredentials .getUserName(), ntcredentials.getHost()); msgBytes = msg3.toByteArray(); } catch (IOException ex) { throw new AuthenticationException( "unable to parse Type2Message", ex); } this.state = TYPE3_MSG_GENERATED; } else { throw new RuntimeException("failed to authenticate"); } response = EncodingUtil.getAsciiString(Base64.encodeBase64(msgBytes)); return "NTLM " + response; } }

وفئة لتسجيل مخطط التفويض، مثل هذا


import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScheme;
import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
import org.apache.commons.httpclient.auth.CredentialsProvider;
import org.apache.commons.httpclient.params.DefaultHttpParams;
import org.apache.commons.httpclient.params.DefaultHttpParamsFactory;
import org.apache.commons.httpclient.params.HttpParams;

/**
 * registers NTLM authentication for apache axis
 * 
 */
public class NtlmJcifsCredentials
{
    public static void register(String password)
    {
        final String username = System.getProperty("user.name");
        final String computername = System.getenv("COMPUTERNAME");
        final String userDomain = System.getenv("USERDOMAIN");
        register(username, password, computername, userDomain);
    }
    public static void register(String username, String password, String userDomain)
    {
        final String computername = System.getenv("COMPUTERNAME");
        register(username, password, computername, userDomain);
    }

    public static void register(
            String username, String password, String computername, String domain)
    {
        final NTCredentials ntCred =
                new NTCredentials(username, password, computername, domain);

        final CredentialsProvider ntlmCredProvider = new CredentialsProvider()
        {
            public Credentials getCredentials(
                    AuthScheme scheme, String host, int port, boolean proxy)
                    throws CredentialsNotAvailableException
            {
                return ntCred;
            }
        };
        final DefaultHttpParamsFactory paramFact =
                new DefaultHttpParamsFactory()
                {
                    @Override
                    protected HttpParams createParams()
                    {
                        HttpParams htp = super.createParams();
                        htp.setParameter(
                                CredentialsProvider.PROVIDER,
                                ntlmCredProvider);
                        return htp;
                    }
                };
        DefaultHttpParams.setHttpParamsFactory(paramFact);

        // we want all our jcifs encoding to be ascii
        jcifs.Config.setProperty("jcifs.encoding", "ASCII");

        // our jcifs implemented NTLM is required for MDW's authentication
        AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, JcifsNtlmScheme.class);
    }
}

في وقت التشغيل أنا اتصل

 NtlmJcifsCredentials.register(username, password, domain) 

أنا بناء كعب نقطة النهاية، وهذا يعمل فقط. كأحداث جانبية مفيدة، سيؤدي هذا الأمر ببساطة باستثناء استثناء إذا فشل في المصادقة - ستستمر فئة Apaches Commons الافتراضية في محاولة الاتصال بلا حدود - والتي في حالة قيام NTLM بإنشاء حسابك بسهولة إلى حسابك من Windows.

لقد عملت ذلك، لكنني لم أقوم بعد بتطبيق دعم الخادم الوكيل في HTTP.http://www.magsoft.nl/share/axis2٪20patch.zip.جميع الجرار التي أستخدمها في دليل مشروع LIB. هناك بعض متطلبات مسار الفصل. أولا، يجب أن يكون AXIS2 HttpClient4.Jar فوق الجرار المحور. علاوة على ذلك، يجب أن لا تزال Commons-httpClient-3.1.Jar في ClassPath، ولكن بعد الجرار httpclient-4.

إليك كيف قمت بتنفيذ العميل:


Scheme http = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
SchemeRegistry sr = new SchemeRegistry();
sr.register(http);
HttpParams httpParms = new BasicHttpParams();
ClientConnectionManager connManager = new ThreadSafeClientConnManager(httpParms, sr);
DefaultHttpClient httpclient = new DefaultHttpClient(connManager, httpParms);
httpclient.getAuthSchemes().register(HttpTransportProperties.Authenticator.NTLM, new NTLMSchemeFactory());
httpclient.getCredentialsProvider().setCredentials(new AuthScope(host, -1), new NTCredentials(user, pass, host, domain));

sps = new SharepointServiceStub(addr.toString());

List authScheme = new ArrayList();
authScheme.add(HttpTransportProperties.Authenticator.NTLM);
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setHost(host);
auth.setDomain(domain);
auth.setUsername(user);
auth.setPassword(pass);
auth.setAuthSchemes(authScheme);
Options options = sps._getServiceClient().getOptions();
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.REUSE_HTTP_CLIENT, true);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CACHED_HTTP_CLIENT, httpclient);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, Boolean.TRUE);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CONNECTION_TIMEOUT, 900000); // 15 minutes
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.SO_TIMEOUT, 180000); // 3 minutes

ولكن بالنسبة لهذا العمل، ستحتاج إلى فئات الأشجار التالية: NtlmschemeFactory.java


package ...;

import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthSchemeFactory;
import org.apache.http.impl.auth.NTLMScheme;
import org.apache.http.params.HttpParams;

public class NTLMSchemeFactory implements AuthSchemeFactory
{

    public NTLMSchemeFactory()
    {
    }

    public AuthScheme newInstance(final HttpParams params)
    {
        return new NTLMScheme(new JCIFSEngine());
    }

}

jcifsscheme.java.


package ...;

import org.apache.http.impl.auth.NTLMScheme;



public class JCIFSScheme extends NTLMScheme
{
    public JCIFSScheme()
    {
        super(new JCIFSEngine());
    }
}

jcifsengine.java.


package ...;

import java.io.IOException;

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;

public class JCIFSEngine implements NTLMEngine
{
    public String generateType1Msg(String domain, String workstation) throws NTLMEngineException
    {

        Type1Message t1m = new Type1Message(Type1Message.getDefaultFlags(), domain, workstation);
        return Base64.encode(t1m.toByteArray());
    }


    public String generateType3Msg(String username, String password, String domain, String workstation, String challenge)
            throws NTLMEngineException
    {
        Type2Message t2m;
        try
        {
            t2m = new Type2Message(Base64.decode(challenge));
        } catch (IOException ex)
        {
            throw new NTLMEngineException("Invalid Type2 message", ex);
        }
        Type3Message t3m = new Type3Message(t2m, password, domain, username, workstation, 0);
        return Base64.encode(t3m.toByteArray());
    }

}

هذه axis2patch.zip. كان المنقذ الحقيقي. وهذا هو ما فعلته:

AXIS2Patch المجمعة مع HTTPClient4.1 Beta1 الذي يحتوي على NTLMV2 بناء في. المستوردة في مشروعي واستيراد httpclient4.1beta1 أيضا.

غيرت وارداتي مثل هذا:

import org.apache.commons.httpclient.auth.AuthenticationException;
import org.apache.commons.httpclient.auth.NTLMScheme;
//import org.apache.commons.httpclient.NTCredentials;
//import org.apache.commons.httpclient.auth.AuthPolicy;

import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.params.AuthPolicy;

وبدون تغيير عدد التعليمات البرمجية، يعمل بشكل مثالي. شكرا!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top